changeset 8056:c65848f2b6a1

8021591: Additional explicit null checks Reviewed-by: psandoz, alanb
author mduigou
date Fri, 13 Sep 2013 11:18:44 -0700
parents c53411f89b4c
children 973fdd9506b2
files src/share/classes/java/util/Collections.java src/share/classes/java/util/Hashtable.java src/share/classes/java/util/IdentityHashMap.java src/share/classes/java/util/Map.java src/share/classes/java/util/TreeMap.java src/share/classes/java/util/concurrent/ConcurrentHashMap.java src/share/classes/javax/security/auth/Subject.java test/java/util/Collection/CollectionDefaults.java test/java/util/Collection/ListDefaults.java test/java/util/Collection/MOAT.java test/java/util/Collection/testlibrary/CollectionAsserts.java test/java/util/Collection/testlibrary/CollectionSupplier.java test/java/util/Collection/testlibrary/ExtendsAbstractCollection.java test/java/util/Collection/testlibrary/ExtendsAbstractList.java test/java/util/Collection/testlibrary/ExtendsAbstractSet.java test/java/util/List/ListDefaults.java test/java/util/Map/Defaults.java
diffstat 17 files changed, 1083 insertions(+), 789 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/java/util/Collections.java	Fri Sep 13 12:20:53 2013 +0100
+++ b/src/share/classes/java/util/Collections.java	Fri Sep 13 11:18:44 2013 -0700
@@ -3900,6 +3900,7 @@
                 return batchRemove(c, true);
             }
             private boolean batchRemove(Collection<?> c, boolean complement) {
+                Objects.requireNonNull(c);
                 boolean modified = false;
                 Iterator<Map.Entry<K,V>> it = iterator();
                 while (it.hasNext()) {
--- a/src/share/classes/java/util/Hashtable.java	Fri Sep 13 12:20:53 2013 +0100
+++ b/src/share/classes/java/util/Hashtable.java	Fri Sep 13 11:18:44 2013 -0700
@@ -957,6 +957,8 @@
 
     @Override
     public synchronized boolean replace(K key, V oldValue, V newValue) {
+        Objects.requireNonNull(oldValue);
+        Objects.requireNonNull(newValue);
         Entry<?,?> tab[] = table;
         int hash = key.hashCode();
         int index = (hash & 0x7FFFFFFF) % tab.length;
@@ -977,6 +979,7 @@
 
     @Override
     public synchronized V replace(K key, V value) {
+        Objects.requireNonNull(value);
         Entry<?,?> tab[] = table;
         int hash = key.hashCode();
         int index = (hash & 0x7FFFFFFF) % tab.length;
--- a/src/share/classes/java/util/IdentityHashMap.java	Fri Sep 13 12:20:53 2013 +0100
+++ b/src/share/classes/java/util/IdentityHashMap.java	Fri Sep 13 11:18:44 2013 -0700
@@ -997,6 +997,7 @@
          * behavior when c is a smaller "normal" (non-identity-based) Set.
          */
         public boolean removeAll(Collection<?> c) {
+            Objects.requireNonNull(c);
             boolean modified = false;
             for (Iterator<K> i = iterator(); i.hasNext(); ) {
                 if (c.contains(i.next())) {
@@ -1212,6 +1213,7 @@
          * behavior when c is a smaller "normal" (non-identity-based) Set.
          */
         public boolean removeAll(Collection<?> c) {
+            Objects.requireNonNull(c);
             boolean modified = false;
             for (Iterator<Map.Entry<K,V>> i = iterator(); i.hasNext(); ) {
                 if (c.contains(i.next())) {
--- a/src/share/classes/java/util/Map.java	Fri Sep 13 12:20:53 2013 +0100
+++ b/src/share/classes/java/util/Map.java	Fri Sep 13 11:18:44 2013 -0700
@@ -805,6 +805,10 @@
      *     return false;
      * }</pre>
      *
+     * The default implementation does not throw NullPointerException
+     * for maps that do not support null values if oldValue is null unless
+     * newValue is also null.
+     *
      * @param key key with which the specified value is associated
      * @param oldValue value expected to be associated with the specified key
      * @param newValue value to be associated with the specified key
@@ -814,8 +818,11 @@
      *         (<a href="Collection.html#optional-restrictions">optional</a>)
      * @throws ClassCastException if the class of a specified key or value
      *         prevents it from being stored in this map
-     * @throws NullPointerException if a specified key or value is null,
+     * @throws NullPointerException if a specified key or newValue is null,
      *         and this map does not permit null keys or values
+     * @throws NullPointerException if oldValue is null and this map does not
+     *         permit null values
+     *         (<a href="Collection.html#optional-restrictions">optional</a>)
      * @throws IllegalArgumentException if some property of a specified key
      *         or value prevents it from being stored in this map
      * @since 1.8
--- a/src/share/classes/java/util/TreeMap.java	Fri Sep 13 12:20:53 2013 +0100
+++ b/src/share/classes/java/util/TreeMap.java	Fri Sep 13 11:18:44 2013 -0700
@@ -1012,7 +1012,7 @@
         int expectedModCount = modCount;
 
         for (Entry<K, V> e = getFirstEntry(); e != null; e = successor(e)) {
-            e.value = Objects.requireNonNull(function.apply(e.key, e.value));
+            e.value = function.apply(e.key, e.value);
 
             if (expectedModCount != modCount) {
                 throw new ConcurrentModificationException();
--- a/src/share/classes/java/util/concurrent/ConcurrentHashMap.java	Fri Sep 13 12:20:53 2013 +0100
+++ b/src/share/classes/java/util/concurrent/ConcurrentHashMap.java	Fri Sep 13 11:18:44 2013 -0700
@@ -49,6 +49,7 @@
 import java.util.Iterator;
 import java.util.Map;
 import java.util.NoSuchElementException;
+import java.util.Objects;
 import java.util.Set;
 import java.util.Spliterator;
 import java.util.concurrent.ConcurrentMap;
@@ -4410,6 +4411,7 @@
         }
 
         public final boolean removeAll(Collection<?> c) {
+            Objects.requireNonNull(c);
             boolean modified = false;
             for (Iterator<E> it = iterator(); it.hasNext();) {
                 if (c.contains(it.next())) {
@@ -4421,6 +4423,7 @@
         }
 
         public final boolean retainAll(Collection<?> c) {
+            Objects.requireNonNull(c);
             boolean modified = false;
             for (Iterator<E> it = iterator(); it.hasNext();) {
                 if (!c.contains(it.next())) {
--- a/src/share/classes/javax/security/auth/Subject.java	Fri Sep 13 12:20:53 2013 +0100
+++ b/src/share/classes/javax/security/auth/Subject.java	Fri Sep 13 11:18:44 2013 -0700
@@ -1186,7 +1186,7 @@
         }
 
         public boolean removeAll(Collection<?> c) {
-
+            Objects.requireNonNull(c);
             boolean modified = false;
             final Iterator<E> e = iterator();
             while (e.hasNext()) {
@@ -1222,7 +1222,7 @@
         }
 
         public boolean retainAll(Collection<?> c) {
-
+            Objects.requireNonNull(c);
             boolean modified = false;
             boolean retain = false;
             final Iterator<E> e = iterator();
--- a/test/java/util/Collection/CollectionDefaults.java	Fri Sep 13 12:20:53 2013 +0100
+++ b/test/java/util/Collection/CollectionDefaults.java	Fri Sep 13 11:18:44 2013 -0700
@@ -21,15 +21,19 @@
  * questions.
  */
 
+import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.LinkedHashSet;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Set;
 
+import java.util.SortedSet;
+
 import org.testng.annotations.DataProvider;
 import org.testng.annotations.Test;
 
@@ -38,43 +42,68 @@
 
 import java.util.TreeMap;
 import java.util.TreeSet;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentSkipListMap;
 import java.util.function.Predicate;
+import java.util.function.Supplier;
 
 /**
  * @test
+ * @summary Unit tests for extension methods on Collection
  * @library testlibrary
- * @build CollectionAsserts CollectionSupplier
+ * @build CollectionAsserts CollectionSupplier ExtendsAbstractSet ExtendsAbstractCollection
  * @run testng CollectionDefaults
- * @summary Unit tests for extension methods on Collection
  */
 public class CollectionDefaults {
 
     public static final Predicate<Integer> pEven = x -> 0 == x % 2;
     public static final Predicate<Integer> pOdd = x -> 1 == x % 2;
 
-    private static final String[] SET_CLASSES = {
-        "java.util.HashSet",
-        "java.util.LinkedHashSet",
-        "java.util.TreeSet"
+    @SuppressWarnings("unchecked")
+    private static final Supplier<?>[] TEST_CLASSES = {
+        // Collection
+        ExtendsAbstractCollection<Integer>::new,
+
+        // Lists
+        java.util.ArrayList<Integer>::new,
+        java.util.LinkedList<Integer>::new,
+        java.util.Vector<Integer>::new,
+        java.util.concurrent.CopyOnWriteArrayList<Integer>::new,
+        ExtendsAbstractList<Integer>::new,
+
+        // Sets
+        java.util.HashSet<Integer>::new,
+        java.util.LinkedHashSet<Integer>::new,
+        java.util.TreeSet<Integer>::new,
+        java.util.concurrent.ConcurrentSkipListSet<Integer>::new,
+        java.util.concurrent.CopyOnWriteArraySet<Integer>::new,
+        ExtendsAbstractSet<Integer>::new
     };
 
     private static final int SIZE = 100;
 
     @DataProvider(name="setProvider", parallel=true)
-    public static Object[][] setCases() {
+    public static Iterator<Object[]> setCases() {
         final List<Object[]> cases = new LinkedList<>();
         cases.add(new Object[] { new HashSet<>() });
         cases.add(new Object[] { new LinkedHashSet<>() });
         cases.add(new Object[] { new TreeSet<>() });
+        cases.add(new Object[] { new java.util.concurrent.ConcurrentSkipListSet<>() });
+        cases.add(new Object[] { new java.util.concurrent.CopyOnWriteArraySet<>() });
+
+        cases.add(new Object[] { new ExtendsAbstractSet<>() });
 
         cases.add(new Object[] { Collections.newSetFromMap(new HashMap<>()) });
         cases.add(new Object[] { Collections.newSetFromMap(new LinkedHashMap()) });
         cases.add(new Object[] { Collections.newSetFromMap(new TreeMap<>()) });
+        cases.add(new Object[] { Collections.newSetFromMap(new ConcurrentHashMap<>()) });
+        cases.add(new Object[] { Collections.newSetFromMap(new ConcurrentSkipListMap<>()) });
 
-        cases.add(new Object[] { new HashSet(){{add(42);}} });
-        cases.add(new Object[] { new LinkedHashSet(){{add(42);}} });
-        cases.add(new Object[] { new TreeSet(){{add(42);}} });
-        return cases.toArray(new Object[0][cases.size()]);
+        cases.add(new Object[] { new HashSet<Integer>(){{add(42);}} });
+        cases.add(new Object[] { new ExtendsAbstractSet<Integer>(){{add(42);}} });
+        cases.add(new Object[] { new LinkedHashSet<Integer>(){{add(42);}} });
+        cases.add(new Object[] { new TreeSet<Integer>(){{add(42);}} });
+        return cases.iterator();
     }
 
     @Test(dataProvider = "setProvider")
@@ -82,57 +111,66 @@
         try {
             set.forEach(null);
             fail("expected NPE not thrown");
-        } catch (NullPointerException npe) {}
+        } catch (NullPointerException expected) {
+                ; // expected
+            }
         try {
             set.removeIf(null);
             fail("expected NPE not thrown");
-        } catch (NullPointerException npe) {}
+        } catch (NullPointerException expected) {
+               ; // expected
+        }
     }
 
     @Test
     public void testForEach() throws Exception {
-        final CollectionSupplier supplier = new CollectionSupplier(SET_CLASSES, SIZE);
-        for (final CollectionSupplier.TestCase test : supplier.get()) {
-            final Set<Integer> original = ((Set<Integer>) test.original);
-            final Set<Integer> set = ((Set<Integer>) test.collection);
+        final CollectionSupplier<Collection<Integer>> supplier = new CollectionSupplier((Supplier<Collection<Integer>>[]) TEST_CLASSES, SIZE);
+
+        for (final CollectionSupplier.TestCase<Collection<Integer>> test : supplier.get()) {
+            final Collection<Integer> original = test.expected;
+            final Collection<Integer> set = test.collection;
 
             try {
                 set.forEach(null);
                 fail("expected NPE not thrown");
-            } catch (NullPointerException npe) {}
-            if (test.className.equals("java.util.HashSet")) {
-                CollectionAsserts.assertContentsUnordered(set, original);
+            } catch (NullPointerException expected) {
+                ; // expected
+            }
+            if (set instanceof Set && !((set instanceof SortedSet) || (set instanceof LinkedHashSet))) {
+                CollectionAsserts.assertContentsUnordered(set, original, test.toString());
             } else {
-                CollectionAsserts.assertContents(set, original);
+                CollectionAsserts.assertContents(set, original, test.toString());
             }
 
             final List<Integer> actual = new LinkedList<>();
             set.forEach(actual::add);
-            if (test.className.equals("java.util.HashSet")) {
-                CollectionAsserts.assertContentsUnordered(actual, set);
-                CollectionAsserts.assertContentsUnordered(actual, original);
+            if (set instanceof Set && !((set instanceof SortedSet) || (set instanceof LinkedHashSet))) {
+                CollectionAsserts.assertContentsUnordered(actual, set, test.toString());
+                CollectionAsserts.assertContentsUnordered(actual, original, test.toString());
             } else {
-                CollectionAsserts.assertContents(actual, set);
-                CollectionAsserts.assertContents(actual, original);
+                CollectionAsserts.assertContents(actual, set, test.toString());
+                CollectionAsserts.assertContents(actual, original, test.toString());
             }
         }
     }
 
     @Test
     public void testRemoveIf() throws Exception {
-        final CollectionSupplier supplier = new CollectionSupplier(SET_CLASSES, SIZE);
-        for (final CollectionSupplier.TestCase test : supplier.get()) {
-            final Set<Integer> original = ((Set<Integer>) test.original);
-            final Set<Integer> set = ((Set<Integer>) test.collection);
+        final CollectionSupplier<Collection<Integer>> supplier = new CollectionSupplier((Supplier<Collection<Integer>>[]) TEST_CLASSES, SIZE);
+        for (final CollectionSupplier.TestCase<Collection<Integer>> test : supplier.get()) {
+            final Collection<Integer> original = test.expected;
+            final Collection<Integer> set = test.collection;
 
             try {
                 set.removeIf(null);
                 fail("expected NPE not thrown");
-            } catch (NullPointerException npe) {}
-            if (test.className.equals("java.util.HashSet")) {
-                CollectionAsserts.assertContentsUnordered(set, original);
+            } catch (NullPointerException expected) {
+                ; // expected
+            }
+            if (set instanceof Set && !((set instanceof SortedSet) || (set instanceof LinkedHashSet))) {
+                CollectionAsserts.assertContentsUnordered(set, original, test.toString());
             } else {
-                CollectionAsserts.assertContents(set, original);
+                CollectionAsserts.assertContents(set, original, test.toString());
             }
 
             set.removeIf(pEven);
--- a/test/java/util/Collection/ListDefaults.java	Fri Sep 13 12:20:53 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,536 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
-import java.util.LinkedList;
-import java.util.Stack;
-import java.util.TreeMap;
-import java.util.TreeSet;
-import java.util.Vector;
-import java.util.concurrent.CopyOnWriteArrayList;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import org.testng.annotations.DataProvider;
-import org.testng.annotations.Test;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertFalse;
-import static org.testng.Assert.assertTrue;
-import static org.testng.Assert.fail;
-
-import java.lang.reflect.Constructor;
-import java.util.ConcurrentModificationException;
-import java.util.function.Predicate;
-
-/**
- * @test
- * @bug 8023367
- * @library testlibrary
- * @build CollectionAsserts CollectionSupplier
- * @run testng ListDefaults
- * @summary Unit tests for extension methods on List
- */
-public class ListDefaults {
-
-    private static final String[] LIST_CLASSES = {
-        "java.util.ArrayList",
-        "java.util.LinkedList",
-        "java.util.Vector",
-        "java.util.concurrent.CopyOnWriteArrayList"
-    };
-
-    private static final String[] LIST_CME_CLASSES = {
-        "java.util.ArrayList",
-        "java.util.Vector"
-    };
-
-    private static final Predicate<Integer> pEven = x -> 0 == x % 2;
-    private static final Predicate<Integer> pOdd = x -> 1 == x % 2;
-
-    private static final Comparator<Integer> BIT_COUNT_COMPARATOR =
-            (x, y) -> Integer.bitCount(x) - Integer.bitCount(y);
-
-    private static final Comparator<AtomicInteger> ATOMIC_INTEGER_COMPARATOR =
-            (x, y) -> x.intValue() - y.intValue();
-
-    private static final int SIZE = 100;
-    private static final int SUBLIST_FROM = 20;
-    private static final int SUBLIST_TO = SIZE - 5;
-    private static final int SUBLIST_SIZE = SUBLIST_TO - SUBLIST_FROM;
-
-    private static interface Callback {
-        void call(List<Integer> list);
-    }
-
-    // call the callback for each recursive subList
-    private void trimmedSubList(final List<Integer> list, final Callback callback) {
-        int size = list.size();
-        if (size > 1) {
-            // trim 1 element from both ends
-            final List<Integer> subList = list.subList(1, size - 1);
-            callback.call(subList);
-            trimmedSubList(subList, callback);
-        }
-    }
-
-    @DataProvider(name="listProvider", parallel=true)
-    public static Object[][] listCases() {
-        final List<Object[]> cases = new LinkedList<>();
-        cases.add(new Object[] { Collections.emptyList() });
-        cases.add(new Object[] { new ArrayList<>() });
-        cases.add(new Object[] { new LinkedList<>() });
-        cases.add(new Object[] { new Vector<>() });
-        cases.add(new Object[] { new Stack<>() });
-        cases.add(new Object[] { new CopyOnWriteArrayList<>() });
-
-        cases.add(new Object[] { new ArrayList(){{add(42);}} });
-        cases.add(new Object[] { new LinkedList(){{add(42);}} });
-        cases.add(new Object[] { new Vector(){{add(42);}} });
-        cases.add(new Object[] { new Stack(){{add(42);}} });
-        cases.add(new Object[] { new CopyOnWriteArrayList(){{add(42);}} });
-        return cases.toArray(new Object[0][cases.size()]);
-    }
-
-    @Test(dataProvider = "listProvider")
-    public void testProvidedWithNull(final List<Integer> list) throws Exception {
-        try {
-            list.forEach(null);
-            fail("expected NPE not thrown");
-        } catch (NullPointerException npe) {}
-        try {
-            list.replaceAll(null);
-            fail("expected NPE not thrown");
-        } catch (NullPointerException npe) {}
-        try {
-            list.removeIf(null);
-            fail("expected NPE not thrown");
-        } catch (NullPointerException npe) {}
-        try {
-            list.sort(null);
-        } catch (Throwable t) {
-            fail("Exception not expected: " + t);
-        }
-    }
-
-    @Test
-    public void testForEach() throws Exception {
-        final CollectionSupplier supplier = new CollectionSupplier(LIST_CLASSES, SIZE);
-        for (final CollectionSupplier.TestCase test : supplier.get()) {
-            final List<Integer> original = ((List<Integer>) test.original);
-            final List<Integer> list = ((List<Integer>) test.collection);
-        }
-        for (final CollectionSupplier.TestCase test : supplier.get()) {
-            final List<Integer> original = ((List<Integer>) test.original);
-            final List<Integer> list = ((List<Integer>) test.collection);
-
-            try {
-                list.forEach(null);
-                fail("expected NPE not thrown");
-            } catch (NullPointerException npe) {}
-            CollectionAsserts.assertContents(list, original);
-
-            final List<Integer> actual = new LinkedList<>();
-            list.forEach(actual::add);
-            CollectionAsserts.assertContents(actual, list);
-            CollectionAsserts.assertContents(actual, original);
-
-            if (original.size() > SUBLIST_SIZE) {
-                final List<Integer> subList = original.subList(SUBLIST_FROM, SUBLIST_TO);
-                final List<Integer> actualSubList = new LinkedList<>();
-                subList.forEach(actualSubList::add);
-                assertEquals(actualSubList.size(), SUBLIST_SIZE);
-                for (int i = 0; i < SUBLIST_SIZE; i++) {
-                    assertEquals(actualSubList.get(i), original.get(i + SUBLIST_FROM));
-                }
-            }
-
-            trimmedSubList(list, new Callback() {
-                @Override
-                public void call(final List<Integer> list) {
-                    final List<Integer> actual = new LinkedList<>();
-                    list.forEach(actual::add);
-                    CollectionAsserts.assertContents(actual, list);
-                }
-            });
-        }
-    }
-
-    @Test
-    public void testRemoveIf() throws Exception {
-        final CollectionSupplier supplier = new CollectionSupplier(LIST_CLASSES, SIZE);
-
-        for (final CollectionSupplier.TestCase test : supplier.get()) {
-            final List<Integer> original = ((List<Integer>) test.original);
-            final List<Integer> list = ((List<Integer>) test.collection);
-
-            try {
-                list.removeIf(null);
-                fail("expected NPE not thrown");
-            } catch (NullPointerException npe) {}
-            CollectionAsserts.assertContents(list, original);
-
-            final AtomicInteger offset = new AtomicInteger(1);
-            while (list.size() > 0) {
-                removeFirst(original, list, offset);
-            }
-        }
-
-        for (final CollectionSupplier.TestCase test : supplier.get()) {
-            final List<Integer> original = ((List<Integer>) test.original);
-            final List<Integer> list = ((List<Integer>) test.collection);
-            list.removeIf(pOdd);
-            for (int i : list) {
-                assertTrue((i % 2) == 0);
-            }
-            for (int i : original) {
-                if (i % 2 == 0) {
-                    assertTrue(list.contains(i));
-                }
-            }
-            list.removeIf(pEven);
-            assertTrue(list.isEmpty());
-        }
-
-        for (final CollectionSupplier.TestCase test : supplier.get()) {
-            final List<Integer> original = ((List<Integer>) test.original);
-            final List<Integer> list = ((List<Integer>) test.collection);
-            final List<Integer> listCopy = new ArrayList<>(list);
-            if (original.size() > SUBLIST_SIZE) {
-                final List<Integer> subList = list.subList(SUBLIST_FROM, SUBLIST_TO);
-                final List<Integer> subListCopy = new ArrayList<>(subList);
-                listCopy.removeAll(subList);
-                subList.removeIf(pOdd);
-                for (int i : subList) {
-                    assertTrue((i % 2) == 0);
-                }
-                for (int i : subListCopy) {
-                    if (i % 2 == 0) {
-                        assertTrue(subList.contains(i));
-                    } else {
-                        assertFalse(subList.contains(i));
-                    }
-                }
-                subList.removeIf(pEven);
-                assertTrue(subList.isEmpty());
-                // elements outside the view should remain
-                CollectionAsserts.assertContents(list, listCopy);
-            }
-        }
-
-        for (final CollectionSupplier.TestCase test : supplier.get()) {
-            final List<Integer> list = ((List<Integer>) test.collection);
-            trimmedSubList(list, new Callback() {
-                @Override
-                public void call(final List<Integer> list) {
-                    final List<Integer> copy = new ArrayList<>(list);
-                    list.removeIf(pOdd);
-                    for (int i : list) {
-                        assertTrue((i % 2) == 0);
-                    }
-                    for (int i : copy) {
-                        if (i % 2 == 0) {
-                            assertTrue(list.contains(i));
-                        } else {
-                            assertFalse(list.contains(i));
-                        }
-                    }
-                }
-            });
-        }
-    }
-
-    // remove the first element
-    private void removeFirst(final List<Integer> original, final List<Integer> list, final AtomicInteger offset) {
-        final AtomicBoolean first = new AtomicBoolean(true);
-        list.removeIf(x -> first.getAndSet(false));
-        CollectionAsserts.assertContents(original.subList(offset.getAndIncrement(), original.size()), list);
-    }
-
-    @Test
-    public void testReplaceAll() throws Exception {
-        final int scale = 3;
-        final CollectionSupplier supplier = new CollectionSupplier(LIST_CLASSES, SIZE);
-        for (final CollectionSupplier.TestCase test : supplier.get()) {
-            final List<Integer> original = ((List<Integer>) test.original);
-            final List<Integer> list = ((List<Integer>) test.collection);
-
-            try {
-                list.replaceAll(null);
-                fail("expected NPE not thrown");
-            } catch (NullPointerException npe) {}
-            CollectionAsserts.assertContents(list, original);
-
-            list.replaceAll(x -> scale * x);
-            for (int i=0; i < original.size(); i++) {
-                assertTrue(list.get(i) == (scale * original.get(i)), "mismatch at index " + i);
-            }
-
-            if (original.size() > SUBLIST_SIZE) {
-                final List<Integer> subList = list.subList(SUBLIST_FROM, SUBLIST_TO);
-                subList.replaceAll(x -> x + 1);
-                // verify elements in view [from, to) were replaced
-                for (int i = 0; i < SUBLIST_SIZE; i++) {
-                    assertTrue(subList.get(i) == ((scale * original.get(i + SUBLIST_FROM)) + 1),
-                            "mismatch at sublist index " + i);
-                }
-                // verify that elements [0, from) remain unmodified
-                for (int i = 0; i < SUBLIST_FROM; i++) {
-                    assertTrue(list.get(i) == (scale * original.get(i)),
-                            "mismatch at original index " + i);
-                }
-                // verify that elements [to, size) remain unmodified
-                for (int i = SUBLIST_TO; i < list.size(); i++) {
-                    assertTrue(list.get(i) == (scale * original.get(i)),
-                            "mismatch at original index " + i);
-                }
-            }
-        }
-
-        for (final CollectionSupplier.TestCase test : supplier.get()) {
-            final List<Integer> list = ((List<Integer>) test.collection);
-            trimmedSubList(list, new Callback() {
-                @Override
-                public void call(final List<Integer> list) {
-                    final List<Integer> copy = new ArrayList<>(list);
-                    final int offset = 5;
-                    list.replaceAll(x -> offset + x);
-                    for (int i=0; i < copy.size(); i++) {
-                        assertTrue(list.get(i) == (offset + copy.get(i)), "mismatch at index " + i);
-                    }
-                }
-            });
-        }
-    }
-
-    @Test
-    public void testSort() throws Exception {
-        final CollectionSupplier supplier = new CollectionSupplier(LIST_CLASSES, SIZE);
-        for (final CollectionSupplier.TestCase test : supplier.get()) {
-            final List<Integer> original = ((List<Integer>) test.original);
-            final List<Integer> list = ((List<Integer>) test.collection);
-            CollectionSupplier.shuffle(list);
-            list.sort(Integer::compare);
-            CollectionAsserts.assertSorted(list, Integer::compare);
-            if (test.name.startsWith("reverse")) {
-                Collections.reverse(list);
-            }
-            CollectionAsserts.assertContents(list, original);
-
-            CollectionSupplier.shuffle(list);
-            list.sort(null);
-            CollectionAsserts.assertSorted(list, Comparator.<Integer>naturalOrder());
-            if (test.name.startsWith("reverse")) {
-                Collections.reverse(list);
-            }
-            CollectionAsserts.assertContents(list, original);
-
-            CollectionSupplier.shuffle(list);
-            list.sort(Comparator.<Integer>naturalOrder());
-            CollectionAsserts.assertSorted(list, Comparator.<Integer>naturalOrder());
-            if (test.name.startsWith("reverse")) {
-                Collections.reverse(list);
-            }
-            CollectionAsserts.assertContents(list, original);
-
-            CollectionSupplier.shuffle(list);
-            list.sort(Comparator.<Integer>reverseOrder());
-            CollectionAsserts.assertSorted(list, Comparator.<Integer>reverseOrder());
-            if (!test.name.startsWith("reverse")) {
-                Collections.reverse(list);
-            }
-            CollectionAsserts.assertContents(list, original);
-
-            CollectionSupplier.shuffle(list);
-            list.sort(BIT_COUNT_COMPARATOR);
-            CollectionAsserts.assertSorted(list, BIT_COUNT_COMPARATOR);
-            // check sort by verifying that bitCount increases and never drops
-            int minBitCount = 0;
-            int bitCount = 0;
-            for (final Integer i : list) {
-                bitCount = Integer.bitCount(i);
-                assertTrue(bitCount >= minBitCount);
-                minBitCount = bitCount;
-            }
-
-            @SuppressWarnings("unchecked")
-            final Class<? extends List<AtomicInteger>> type =
-                    (Class<? extends List<AtomicInteger>>) Class.forName(test.className);
-            final Constructor<? extends List<AtomicInteger>> defaultConstructor = type.getConstructor();
-            final List<AtomicInteger> incomparables = (List<AtomicInteger>) defaultConstructor.newInstance();
-
-            for (int i=0; i < test.original.size(); i++) {
-                incomparables.add(new AtomicInteger(i));
-            }
-            CollectionSupplier.shuffle(incomparables);
-            incomparables.sort(ATOMIC_INTEGER_COMPARATOR);
-            for (int i=0; i < test.original.size(); i++) {
-                assertEquals(i, incomparables.get(i).intValue());
-            }
-
-            if (original.size() > SUBLIST_SIZE) {
-                final List<Integer> copy = new ArrayList<>(list);
-                final List<Integer> subList = list.subList(SUBLIST_FROM, SUBLIST_TO);
-                CollectionSupplier.shuffle(subList);
-                subList.sort(Comparator.<Integer>naturalOrder());
-                CollectionAsserts.assertSorted(subList, Comparator.<Integer>naturalOrder());
-                // verify that elements [0, from) remain unmodified
-                for (int i = 0; i < SUBLIST_FROM; i++) {
-                    assertTrue(list.get(i) == copy.get(i),
-                            "mismatch at index " + i);
-                }
-                // verify that elements [to, size) remain unmodified
-                for (int i = SUBLIST_TO; i < list.size(); i++) {
-                    assertTrue(list.get(i) == copy.get(i),
-                            "mismatch at index " + i);
-                }
-            }
-        }
-
-        for (final CollectionSupplier.TestCase test : supplier.get()) {
-            final List<Integer> list = ((List<Integer>) test.collection);
-            trimmedSubList(list, new Callback() {
-                @Override
-                public void call(final List<Integer> list) {
-                    final List<Integer> copy = new ArrayList<>(list);
-                    CollectionSupplier.shuffle(list);
-                    list.sort(Comparator.<Integer>naturalOrder());
-                    CollectionAsserts.assertSorted(list, Comparator.<Integer>naturalOrder());
-                }
-            });
-        }
-    }
-
-    @Test
-    public void testForEachThrowsCME() throws Exception {
-        final CollectionSupplier supplier = new CollectionSupplier(LIST_CME_CLASSES, SIZE);
-        for (final CollectionSupplier.TestCase test : supplier.get()) {
-            final List<Integer> list = ((List<Integer>) test.collection);
-            if (list.size() <= 1) {
-                continue;
-            }
-            boolean gotException = false;
-            try {
-                // bad predicate that modifies its list, should throw CME
-                list.forEach((x) -> {list.add(x);});
-            } catch (ConcurrentModificationException cme) {
-                gotException = true;
-            }
-            if (!gotException) {
-                fail("expected CME was not thrown from " + test);
-            }
-        }
-    }
-
-    @Test
-    public void testRemoveIfThrowsCME() throws Exception {
-        final CollectionSupplier supplier = new CollectionSupplier(LIST_CME_CLASSES, SIZE);
-        for (final CollectionSupplier.TestCase test : supplier.get()) {
-            final List<Integer> list = ((List<Integer>) test.collection);
-            if (list.size() <= 1) {
-                continue;
-            }
-            boolean gotException = false;
-            try {
-                // bad predicate that modifies its list, should throw CME
-                list.removeIf((x) -> {return list.add(x);});
-            } catch (ConcurrentModificationException cme) {
-                gotException = true;
-            }
-            if (!gotException) {
-                fail("expected CME was not thrown from " + test);
-            }
-        }
-    }
-
-    @Test
-    public void testReplaceAllThrowsCME() throws Exception {
-        final CollectionSupplier supplier = new CollectionSupplier(LIST_CME_CLASSES, SIZE);
-        for (final CollectionSupplier.TestCase test : supplier.get()) {
-            final List<Integer> list = ((List<Integer>) test.collection);
-            if (list.size() <= 1) {
-                continue;
-            }
-            boolean gotException = false;
-            try {
-                // bad predicate that modifies its list, should throw CME
-                list.replaceAll(x -> {int n = 3 * x; list.add(n); return n;});
-            } catch (ConcurrentModificationException cme) {
-                gotException = true;
-            }
-            if (!gotException) {
-                fail("expected CME was not thrown from " + test);
-            }
-        }
-    }
-
-    @Test
-    public void testSortThrowsCME() throws Exception {
-        final CollectionSupplier supplier = new CollectionSupplier(LIST_CME_CLASSES, SIZE);
-        for (final CollectionSupplier.TestCase test : supplier.get()) {
-            final List<Integer> list = ((List<Integer>) test.collection);
-            if (list.size() <= 1) {
-                continue;
-            }
-            boolean gotException = false;
-            try {
-                // bad predicate that modifies its list, should throw CME
-                list.sort((x, y) -> {list.add(x); return x - y;});
-            } catch (ConcurrentModificationException cme) {
-                gotException = true;
-            }
-            if (!gotException) {
-                fail("expected CME was not thrown from " + test);
-            }
-        }
-    }
-
-    private static final List<Integer> SLICED_EXPECTED = Arrays.asList(0, 1, 2, 3, 5, 6, 7, 8, 9);
-    private static final List<Integer> SLICED_EXPECTED2 = Arrays.asList(0, 1, 2, 5, 6, 7, 8, 9);
-
-    @DataProvider(name="shortIntListProvider", parallel=true)
-    public static Object[][] intListCases() {
-        final Integer[] DATA = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
-        final List<Object[]> cases = new LinkedList<>();
-        cases.add(new Object[] { new ArrayList<>(Arrays.asList(DATA)) });
-        cases.add(new Object[] { new LinkedList<>(Arrays.asList(DATA)) });
-        cases.add(new Object[] { new Vector<>(Arrays.asList(DATA)) });
-        cases.add(new Object[] { new CopyOnWriteArrayList<>(Arrays.asList(DATA)) });
-        return cases.toArray(new Object[0][cases.size()]);
-    }
-
-    @Test(dataProvider = "shortIntListProvider")
-    public void testRemoveIfFromSlice(final List<Integer> list) throws Exception {
-        final List<Integer> sublist = list.subList(3, 6);
-        assertTrue(sublist.removeIf(x -> x == 4));
-        CollectionAsserts.assertContents(list, SLICED_EXPECTED);
-
-        final List<Integer> sublist2 = list.subList(2, 5);
-        assertTrue(sublist2.removeIf(x -> x == 3));
-        CollectionAsserts.assertContents(list, SLICED_EXPECTED2);
-    }
-}
--- a/test/java/util/Collection/MOAT.java	Fri Sep 13 12:20:53 2013 +0100
+++ b/test/java/util/Collection/MOAT.java	Fri Sep 13 11:18:44 2013 -0700
@@ -400,8 +400,6 @@
     // If add(null) succeeds, contains(null) & remove(null) should succeed
     //----------------------------------------------------------------
     private static void testNullElement(Collection<Integer> c) {
-        // !!!! 5018849: (coll) TreeSet.contains(null) does not agree with Javadoc
-        if (c instanceof TreeSet) return;
 
         try {
             check(c.add(null));
--- a/test/java/util/Collection/testlibrary/CollectionAsserts.java	Fri Sep 13 12:20:53 2013 +0100
+++ b/test/java/util/Collection/testlibrary/CollectionAsserts.java	Fri Sep 13 11:18:44 2013 -0700
@@ -41,6 +41,10 @@
  */
 public class CollectionAsserts {
 
+    private CollectionAsserts() {
+        // no instances
+    }
+
     public static void assertCountSum(Iterable<? super Integer> it, int count, int sum) {
         assertCountSum(it.iterator(), count, sum);
     }
@@ -117,10 +121,18 @@
     }
 
     public static<T> void assertContents(Iterable<T> actual, Iterable<T> expected) {
-        assertContents(actual.iterator(), expected.iterator());
+        assertContents(actual, expected, null);
+    }
+
+    public static<T> void assertContents(Iterable<T> actual, Iterable<T> expected, String msg) {
+        assertContents(actual.iterator(), expected.iterator(), msg);
     }
 
     public static<T> void assertContents(Iterator<T> actual, Iterator<T> expected) {
+        assertContents(actual, expected, null);
+    }
+
+    public static<T> void assertContents(Iterator<T> actual, Iterator<T> expected, String msg) {
         List<T> history = new ArrayList<>();
 
         while (expected.hasNext()) {
@@ -128,20 +140,23 @@
                 List<T> expectedData = new ArrayList<>(history);
                 while (expected.hasNext())
                     expectedData.add(expected.next());
-                fail(String.format("Premature end of data; expected=%s, found=%s", expectedData, history));
+                fail(String.format("%s Premature end of data; expected=%s, found=%s",
+                    (msg == null ? "" : msg), expectedData, history));
             }
             T a = actual.next();
             T e = expected.next();
             history.add(a);
 
             if (!Objects.equals(a, e))
-                fail(String.format("Data mismatch; preceding=%s, nextExpected=%s, nextFound=%s", history, e, a));
+                fail(String.format("%s Data mismatch; preceding=%s, nextExpected=%s, nextFound=%s",
+                    (msg == null ? "" : msg), history, e, a));
         }
         if (actual.hasNext()) {
             List<T> rest = new ArrayList<>();
             while (actual.hasNext())
                 rest.add(actual.next());
-            fail(String.format("Unexpected data %s after %s", rest, history));
+            fail(String.format("%s Unexpected data %s after %s",
+                (msg == null ? "" : msg), rest, history));
         }
     }
 
@@ -151,30 +166,21 @@
         assertContents(actual, Arrays.asList(expected).iterator());
     }
 
-    public static <T> boolean equalsContentsUnordered(Iterable<T> a, Iterable<T> b) {
-        Set<T> sa = new HashSet<>();
-        for (T t : a) {
-            sa.add(t);
-        }
+    public static<T extends Comparable<? super T>> void assertContentsUnordered(Iterable<T> actual, Iterable<T> expected) {
+        assertContentsUnordered(actual, expected, null);
+    }
 
-        Set<T> sb = new HashSet<>();
-        for (T t : b) {
-            sb.add(t);
+    public static<T extends Comparable<? super T>> void assertContentsUnordered(Iterable<T> actual, Iterable<T> expected, String msg) {
+        List<T> allExpected = new ArrayList<>();
+        for (T t : expected) {
+            allExpected.add(t);
         }
 
-        return Objects.equals(sa, sb);
-    }
+        for (T t : actual) {
+            assertTrue(allExpected.remove(t), msg + " element '" + String.valueOf(t) + "' not found");
+        }
 
-    public static<T extends Comparable<? super T>> void assertContentsUnordered(Iterable<T> actual, Iterable<T> expected) {
-        ArrayList<T> one = new ArrayList<>();
-        for (T t : actual)
-            one.add(t);
-        ArrayList<T> two = new ArrayList<>();
-        for (T t : expected)
-            two.add(t);
-        Collections.sort(one);
-        Collections.sort(two);
-        assertContents(one, two);
+        assertTrue(allExpected.isEmpty(), msg + "expected contained additional elements");
     }
 
     static <T> void assertSplitContents(Iterable<Iterable<T>> splits, Iterable<T> list) {
--- a/test/java/util/Collection/testlibrary/CollectionSupplier.java	Fri Sep 13 12:20:53 2013 +0100
+++ b/test/java/util/Collection/testlibrary/CollectionSupplier.java	Fri Sep 13 11:18:44 2013 -0700
@@ -29,13 +29,11 @@
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Random;
-import java.util.Set;
 
 import org.testng.TestException;
 
 import static org.testng.Assert.assertTrue;
 
-import java.lang.reflect.Constructor;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.function.Supplier;
@@ -44,15 +42,15 @@
  * @library
  * @summary A Supplier of test cases for Collection tests
  */
-public final class CollectionSupplier implements Supplier<Iterable<CollectionSupplier.TestCase>> {
+public final class CollectionSupplier<C extends Collection<Integer>> implements Supplier<Iterable<CollectionSupplier.TestCase<C>>> {
 
-    private final String[] classNames;
+    private final Supplier<C>[] classes;
     private final int size;
 
     /**
      * A Collection test case.
      */
-    public static final class TestCase {
+    public static final class TestCase<C extends Collection<Integer>> {
 
         /**
          * The name of the test case.
@@ -60,57 +58,45 @@
         public final String name;
 
         /**
-         * Class name of the instantiated Collection.
-         */
-        public final String className;
-
-        /**
          * Unmodifiable reference collection, useful for comparisons.
          */
-        public final Collection<Integer> original;
+        public final List<Integer> expected;
 
         /**
          * A modifiable test collection.
          */
-        public final Collection<Integer> collection;
+        public final C collection;
 
         /**
          * Create a Collection test case.
+         *
          * @param name name of the test case
-         * @param className class name of the instantiated collection
-         * @param original reference collection
+         * @param expected reference collection
          * @param collection the modifiable test collection
          */
-        public TestCase(String name, String className,
-                Collection<Integer> original, Collection<Integer> collection) {
+        public TestCase(String name, C collection) {
             this.name = name;
-            this.className = className;
-            this.original =
-                    List.class.isAssignableFrom(original.getClass()) ?
-                    Collections.unmodifiableList((List<Integer>) original) :
-                    Set.class.isAssignableFrom(original.getClass()) ?
-                    Collections.unmodifiableSet((Set<Integer>) original) :
-                    Collections.unmodifiableCollection(original);
+            this.expected = Collections.unmodifiableList(
+                Arrays.asList(collection.toArray(new Integer[0])));
             this.collection = collection;
         }
 
         @Override
         public String toString() {
-            return name + " " + className +
-                    "\n original: " + original +
-                    "\n   target: " + collection;
+            return name + " " + collection.getClass().toString();
         }
     }
 
     /**
      * Shuffle a list using a PRNG with known seed for repeatability
+     *
      * @param list the list to be shuffled
      */
     public static <E> void shuffle(final List<E> list) {
         // PRNG with known seed for repeatable tests
         final Random prng = new Random(13);
         final int size = list.size();
-        for (int i=0; i < size; i++) {
+        for (int i = 0; i < size; i++) {
             // random index in interval [i, size)
             final int j = i + prng.nextInt(size - i);
             // swap elements at indices i & j
@@ -127,178 +113,133 @@
      * @param classNames class names that implement {@code Collection}
      * @param size the desired size of each collection
      */
-    public CollectionSupplier(String[] classNames, int size) {
-        this.classNames = Arrays.copyOf(classNames, classNames.length);
+    public CollectionSupplier(Supplier<C>[] classes, int size) {
+        this.classes = Arrays.copyOf(classes, classes.length);
         this.size = size;
     }
 
     @Override
-    public Iterable<TestCase> get() {
-        try {
-            return getThrows();
-        } catch (Exception e) {
-            throw new TestException(e);
-        }
-    }
+    public Iterable<TestCase<C>> get() {
+        final Collection<TestCase<C>> cases = new LinkedList<>();
+        for (final Supplier<C> type : classes) {
+            try {
+                final Collection<Integer> empty = type.get();
+                cases.add(new TestCase("empty", empty));
 
-    private Iterable<TestCase> getThrows() throws Exception {
-        final Collection<TestCase> collections = new LinkedList<>();
-        for (final String className : classNames) {
-            @SuppressWarnings("unchecked")
-            final Class<? extends Collection<Integer>> type =
-                    (Class<? extends Collection<Integer>>) Class.forName(className);
-            final Constructor<? extends Collection<Integer>>
-                    defaultConstructor = type.getConstructor();
-            final Constructor<? extends Collection<Integer>>
-                    copyConstructor = type.getConstructor(Collection.class);
+                final Collection<Integer> single = type.get();
+                single.add(42);
+                cases.add(new TestCase("single", single));
 
-            final Collection<Integer> empty = defaultConstructor.newInstance();
-            collections.add(new TestCase("empty",
-                    className,
-                    copyConstructor.newInstance(empty),
-                    empty));
+                final Collection<Integer> regular = type.get();
+                for (int i = 0; i < size; i++) {
+                    regular.add(i);
+                }
+                cases.add(new TestCase("regular", regular));
 
-            final Collection<Integer> single = defaultConstructor.newInstance();
-            single.add(42);
-            collections.add(new TestCase("single",
-                    className,
-                    copyConstructor.newInstance(single),
-                    single));
-
-            final Collection<Integer> regular = defaultConstructor.newInstance();
-            for (int i=0; i < size; i++) {
-                regular.add(i);
-            }
-            collections.add(new TestCase("regular",
-                    className,
-                    copyConstructor.newInstance(regular),
-                    regular));
+                final Collection<Integer> reverse = type.get();
+                for (int i = size; i >= 0; i--) {
+                    reverse.add(i);
+                }
+                cases.add(new TestCase("reverse", reverse));
 
-            final Collection<Integer> reverse = defaultConstructor.newInstance();
-            for (int i=size; i >= 0; i--) {
-                reverse.add(i);
-            }
-            collections.add(new TestCase("reverse",
-                    className,
-                    copyConstructor.newInstance(reverse),
-                    reverse));
+                final Collection<Integer> odds = type.get();
+                for (int i = 0; i < size; i++) {
+                    odds.add((i * 2) + 1);
+                }
+                cases.add(new TestCase("odds", odds));
 
-            final Collection<Integer> odds = defaultConstructor.newInstance();
-            for (int i=0; i < size; i++) {
-                odds.add((i * 2) + 1);
-            }
-            collections.add(new TestCase("odds",
-                    className,
-                    copyConstructor.newInstance(odds),
-                    odds));
+                final Collection<Integer> evens = type.get();
+                for (int i = 0; i < size; i++) {
+                    evens.add(i * 2);
+                }
+                cases.add(new TestCase("evens", evens));
 
-            final Collection<Integer> evens = defaultConstructor.newInstance();
-            for (int i=0; i < size; i++) {
-                evens.add(i * 2);
-            }
-            collections.add(new TestCase("evens",
-                    className,
-                    copyConstructor.newInstance(evens),
-                    evens));
-
-            final Collection<Integer> fibonacci = defaultConstructor.newInstance();
-            int prev2 = 0;
-            int prev1 = 1;
-            for (int i=0; i < size; i++) {
-                final int n = prev1 + prev2;
-                if (n < 0) { // stop on overflow
-                    break;
+                final Collection<Integer> fibonacci = type.get();
+                int prev2 = 0;
+                int prev1 = 1;
+                for (int i = 0; i < size; i++) {
+                    final int n = prev1 + prev2;
+                    if (n < 0) { // stop on overflow
+                        break;
+                    }
+                    fibonacci.add(n);
+                    prev2 = prev1;
+                    prev1 = n;
                 }
-                fibonacci.add(n);
-                prev2 = prev1;
-                prev1 = n;
-            }
-            collections.add(new TestCase("fibonacci",
-                    className,
-                    copyConstructor.newInstance(fibonacci),
-                    fibonacci));
+                cases.add(new TestCase("fibonacci", fibonacci));
 
             // variants where the size of the backing storage != reported size
-            // created by removing half of the elements
+                // created by removing half of the elements
+                final Collection<Integer> emptyWithSlack = type.get();
+                emptyWithSlack.add(42);
+                assertTrue(emptyWithSlack.remove(42));
+                cases.add(new TestCase("emptyWithSlack", emptyWithSlack));
 
-            final Collection<Integer> emptyWithSlack = defaultConstructor.newInstance();
-            emptyWithSlack.add(42);
-            assertTrue(emptyWithSlack.remove(42));
-            collections.add(new TestCase("emptyWithSlack",
-                    className,
-                    copyConstructor.newInstance(emptyWithSlack),
-                    emptyWithSlack));
-
-            final Collection<Integer> singleWithSlack = defaultConstructor.newInstance();
-            singleWithSlack.add(42);
-            singleWithSlack.add(43);
-            assertTrue(singleWithSlack.remove(43));
-            collections.add(new TestCase("singleWithSlack",
-                    className,
-                    copyConstructor.newInstance(singleWithSlack),
-                    singleWithSlack));
+                final Collection<Integer> singleWithSlack = type.get();
+                singleWithSlack.add(42);
+                singleWithSlack.add(43);
+                assertTrue(singleWithSlack.remove(43));
+                cases.add(new TestCase("singleWithSlack", singleWithSlack));
 
-            final Collection<Integer> regularWithSlack = defaultConstructor.newInstance();
-            for (int i=0; i < (2 * size); i++) {
-                regularWithSlack.add(i);
-            }
-            assertTrue(regularWithSlack.removeIf((x) -> {return x >= size;}));
-            collections.add(new TestCase("regularWithSlack",
-                    className,
-                    copyConstructor.newInstance(regularWithSlack),
-                    regularWithSlack));
+                final Collection<Integer> regularWithSlack = type.get();
+                for (int i = 0; i < (2 * size); i++) {
+                    regularWithSlack.add(i);
+                }
+                assertTrue(regularWithSlack.removeIf((x) -> {
+                    return x >= size;
+                }));
+                cases.add(new TestCase("regularWithSlack", regularWithSlack));
 
-            final Collection<Integer> reverseWithSlack = defaultConstructor.newInstance();
-            for (int i=2 * size; i >= 0; i--) {
-                reverseWithSlack.add(i);
-            }
-            assertTrue(reverseWithSlack.removeIf((x) -> {return x < size;}));
-            collections.add(new TestCase("reverseWithSlack",
-                    className,
-                    copyConstructor.newInstance(reverseWithSlack),
-                    reverseWithSlack));
+                final Collection<Integer> reverseWithSlack = type.get();
+                for (int i = 2 * size; i >= 0; i--) {
+                    reverseWithSlack.add(i);
+                }
+                assertTrue(reverseWithSlack.removeIf((x) -> {
+                    return x < size;
+                }));
+                cases.add(new TestCase("reverseWithSlack", reverseWithSlack));
 
-            final Collection<Integer> oddsWithSlack = defaultConstructor.newInstance();
-            for (int i = 0; i < 2 * size; i++) {
-                oddsWithSlack.add((i * 2) + 1);
-            }
-            assertTrue(oddsWithSlack.removeIf((x) -> {return x >= size;}));
-            collections.add(new TestCase("oddsWithSlack",
-                    className,
-                    copyConstructor.newInstance(oddsWithSlack),
-                    oddsWithSlack));
+                final Collection<Integer> oddsWithSlack = type.get();
+                for (int i = 0; i < 2 * size; i++) {
+                    oddsWithSlack.add((i * 2) + 1);
+                }
+                assertTrue(oddsWithSlack.removeIf((x) -> {
+                    return x >= size;
+                }));
+                cases.add(new TestCase("oddsWithSlack", oddsWithSlack));
+
+                final Collection<Integer> evensWithSlack = type.get();
+                for (int i = 0; i < 2 * size; i++) {
+                    evensWithSlack.add(i * 2);
+                }
+                assertTrue(evensWithSlack.removeIf((x) -> {
+                    return x >= size;
+                }));
+                cases.add(new TestCase("evensWithSlack", evensWithSlack));
 
-            final Collection<Integer> evensWithSlack = defaultConstructor.newInstance();
-            for (int i = 0; i < 2 * size; i++) {
-                evensWithSlack.add(i * 2);
+                final Collection<Integer> fibonacciWithSlack = type.get();
+                prev2 = 0;
+                prev1 = 1;
+                for (int i = 0; i < size; i++) {
+                    final int n = prev1 + prev2;
+                    if (n < 0) { // stop on overflow
+                        break;
+                    }
+                    fibonacciWithSlack.add(n);
+                    prev2 = prev1;
+                    prev1 = n;
+                }
+                assertTrue(fibonacciWithSlack.removeIf((x) -> {
+                    return x < 20;
+                }));
+                cases.add(new TestCase("fibonacciWithSlack",
+                    fibonacciWithSlack));
+            } catch (Exception failed) {
+                throw new TestException(failed);
             }
-            assertTrue(evensWithSlack.removeIf((x) -> {return x >= size;}));
-            collections.add(new TestCase("evensWithSlack",
-                    className,
-                    copyConstructor.newInstance(evensWithSlack),
-                    evensWithSlack));
-
-            final Collection<Integer> fibonacciWithSlack = defaultConstructor.newInstance();
-            prev2 = 0;
-            prev1 = 1;
-            for (int i=0; i < size; i++) {
-                final int n = prev1 + prev2;
-                if (n < 0) { // stop on overflow
-                    break;
-                }
-                fibonacciWithSlack.add(n);
-                prev2 = prev1;
-                prev1 = n;
-            }
-            assertTrue(fibonacciWithSlack.removeIf((x) -> {return x < 20;}));
-            collections.add(new TestCase("fibonacciWithSlack",
-                    className,
-                    copyConstructor.newInstance(fibonacciWithSlack),
-                    fibonacciWithSlack));
-
         }
 
-        return collections;
+        return cases;
     }
 
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/util/Collection/testlibrary/ExtendsAbstractCollection.java	Fri Sep 13 11:18:44 2013 -0700
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+import java.util.AbstractCollection;
+import java.util.HashSet;
+import java.util.AbstractSet;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.function.Supplier;
+
+/**
+ * @library
+ *
+ * A simple mutable collection implementation that provides only default
+ * implementations of all methods. ie. none of the Collection interface default
+ * methods have overridden implementations.
+ *
+ * @param <E> type of collection elements
+ */
+public class ExtendsAbstractCollection<E> extends AbstractCollection<E> {
+
+    protected final Collection<E> coll;
+
+    public ExtendsAbstractCollection() {
+        this(ArrayList<E>::new);
+    }
+
+    public ExtendsAbstractCollection(Collection<E> source) {
+        this();
+        coll.addAll(source);
+    }
+
+    protected ExtendsAbstractCollection(Supplier<Collection<E>> backer) {
+        this.coll = backer.get();
+    }
+
+    public boolean add(E element) {
+        return coll.add(element);
+    }
+
+    public boolean remove(Object element) {
+        return coll.remove(element);
+    }
+
+    public Iterator<E> iterator() {
+        return new Iterator<E>() {
+            Iterator<E> source = coll.iterator();
+
+            public boolean hasNext() {
+                return source.hasNext();
+            }
+
+            public E next() {
+                return source.next();
+            }
+
+            public void remove() {
+                source.remove();
+            }
+        };
+    }
+
+    public int size() {
+        return coll.size();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/util/Collection/testlibrary/ExtendsAbstractList.java	Fri Sep 13 11:18:44 2013 -0700
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+import java.util.ArrayList;
+import java.util.AbstractList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.function.Supplier;
+
+/**
+ * @library
+ *
+ * A simple mutable list implementation that provides only default
+ * implementations of all methods. ie. none of the List interface default
+ * methods have overridden implementations.
+ *
+ * @param <E> type of list elements
+ */
+public class ExtendsAbstractList<E> extends AbstractList<E> {
+
+    protected final List<E> list;
+
+    public ExtendsAbstractList() {
+        this(ArrayList<E>::new);
+    }
+
+    protected ExtendsAbstractList(Supplier<List<E>> supplier) {
+        this.list = supplier.get();
+    }
+
+    public ExtendsAbstractList(Collection<E> source) {
+        this();
+        addAll(source);
+    }
+
+    public boolean add(E element) {
+        return list.add(element);
+    }
+
+    public E get(int index) {
+        return list.get(index);
+    }
+
+    public boolean remove(Object element) {
+        return list.remove(element);
+    }
+
+    public E set(int index, E element) {
+        return list.set(index, element);
+    }
+
+    public void add(int index, E element) {
+        list.add(index, element);
+    }
+
+    public E remove(int index) {
+        return list.remove(index);
+    }
+
+    public Iterator<E> iterator() {
+        return new Iterator<E>() {
+            Iterator<E> source = list.iterator();
+
+            public boolean hasNext() {
+                return source.hasNext();
+            }
+
+            public E next() {
+                return source.next();
+            }
+
+            public void remove() {
+                source.remove();
+            }
+        };
+    }
+
+    public int size() {
+        return list.size();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/util/Collection/testlibrary/ExtendsAbstractSet.java	Fri Sep 13 11:18:44 2013 -0700
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+import java.util.HashSet;
+import java.util.AbstractSet;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.function.Supplier;
+
+/**
+ * @library
+ *
+ * A simple mutable set implementation that provides only default
+ * implementations of all methods. ie. none of the Set interface default methods
+ * have overridden implementations.
+ *
+ * @param <E> type of set members
+ */
+public class ExtendsAbstractSet<E> extends AbstractSet<E> {
+
+    protected final Set<E> set;
+
+    public ExtendsAbstractSet() {
+        this(HashSet<E>::new);
+    }
+
+    public ExtendsAbstractSet(Collection<E> source) {
+        this();
+        addAll(source);
+    }
+
+    protected ExtendsAbstractSet(Supplier<Set<E>> backer) {
+        this.set = backer.get();
+    }
+
+    public boolean add(E element) {
+        return set.add(element);
+    }
+
+    public boolean remove(Object element) {
+        return set.remove(element);
+    }
+
+    public Iterator<E> iterator() {
+        return new Iterator<E>() {
+            Iterator<E> source = set.iterator();
+
+            public boolean hasNext() {
+                return source.hasNext();
+            }
+
+            public E next() {
+                return source.next();
+            }
+
+            public void remove() {
+                source.remove();
+            }
+        };
+    }
+
+    public int size() {
+        return set.size();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/util/List/ListDefaults.java	Fri Sep 13 11:18:44 2013 -0700
@@ -0,0 +1,535 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.LinkedList;
+import java.util.Stack;
+import java.util.Vector;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+
+import java.lang.reflect.Constructor;
+import java.util.ConcurrentModificationException;
+import java.util.function.Predicate;
+import java.util.function.Supplier;
+
+/**
+ * @test
+ * @summary Unit tests for extension methods on List
+ * @bug 8023367
+ * @library ../Collection/testlibrary
+ * @build CollectionAsserts CollectionSupplier ExtendsAbstractList
+ * @run testng ListDefaults
+ */
+public class ListDefaults {
+
+    private static final Supplier<?>[] LIST_CLASSES = {
+        java.util.ArrayList::new,
+        java.util.LinkedList::new,
+        java.util.Vector::new,
+        java.util.concurrent.CopyOnWriteArrayList::new,
+        ExtendsAbstractList::new
+     };
+
+    private static final Supplier<?>[] LIST_CME_CLASSES = {
+        java.util.ArrayList::new,
+        java.util.Vector::new
+     };
+
+    private static final Predicate<Integer> pEven = x -> 0 == x % 2;
+    private static final Predicate<Integer> pOdd = x -> 1 == x % 2;
+
+    private static final Comparator<Integer> BIT_COUNT_COMPARATOR =
+            (x, y) -> Integer.bitCount(x) - Integer.bitCount(y);
+
+    private static final Comparator<AtomicInteger> ATOMIC_INTEGER_COMPARATOR =
+            (x, y) -> x.intValue() - y.intValue();
+
+    private static final int SIZE = 100;
+    private static final int SUBLIST_FROM = 20;
+    private static final int SUBLIST_TO = SIZE - 5;
+    private static final int SUBLIST_SIZE = SUBLIST_TO - SUBLIST_FROM;
+
+    private static interface Callback {
+        void call(List<Integer> list);
+    }
+
+    // call the callback for each recursive subList
+    private void trimmedSubList(final List<Integer> list, final Callback callback) {
+        int size = list.size();
+        if (size > 1) {
+            // trim 1 element from both ends
+            final List<Integer> subList = list.subList(1, size - 1);
+            callback.call(subList);
+            trimmedSubList(subList, callback);
+        }
+    }
+
+    @DataProvider(name="listProvider", parallel=true)
+    public static Object[][] listCases() {
+        final List<Object[]> cases = new LinkedList<>();
+        cases.add(new Object[] { Collections.emptyList() });
+        cases.add(new Object[] { new ArrayList<>() });
+        cases.add(new Object[] { new LinkedList<>() });
+        cases.add(new Object[] { new Vector<>() });
+        cases.add(new Object[] { new Stack<>() });
+        cases.add(new Object[] { new CopyOnWriteArrayList<>() });
+
+        cases.add(new Object[] { new ArrayList(){{add(42);}} });
+        cases.add(new Object[] { new LinkedList(){{add(42);}} });
+        cases.add(new Object[] { new Vector(){{add(42);}} });
+        cases.add(new Object[] { new Stack(){{add(42);}} });
+        cases.add(new Object[] { new CopyOnWriteArrayList(){{add(42);}} });
+        return cases.toArray(new Object[0][cases.size()]);
+    }
+
+    @Test(dataProvider = "listProvider")
+    public void testProvidedWithNull(final List<Integer> list) throws Exception {
+        try {
+            list.forEach(null);
+            fail("expected NPE not thrown");
+        } catch (NullPointerException npe) {}
+        try {
+            list.replaceAll(null);
+            fail("expected NPE not thrown");
+        } catch (NullPointerException npe) {}
+        try {
+            list.removeIf(null);
+            fail("expected NPE not thrown");
+        } catch (NullPointerException npe) {}
+        try {
+            list.sort(null);
+        } catch (Throwable t) {
+            fail("Exception not expected: " + t);
+        }
+    }
+
+    @Test
+    public void testForEach() throws Exception {
+        final CollectionSupplier<List<Integer>> supplier = new CollectionSupplier((Supplier<List<Integer>>[])LIST_CLASSES, SIZE);
+        for (final CollectionSupplier.TestCase<List<Integer>> test : supplier.get()) {
+            final List<Integer> original = ((List<Integer>) test.expected);
+            final List<Integer> list = ((List<Integer>) test.collection);
+
+            try {
+                list.forEach(null);
+                fail("expected NPE not thrown");
+            } catch (NullPointerException npe) {}
+            CollectionAsserts.assertContents(list, original);
+
+            final List<Integer> actual = new LinkedList<>();
+            list.forEach(actual::add);
+            CollectionAsserts.assertContents(actual, list);
+            CollectionAsserts.assertContents(actual, original);
+
+            if (original.size() > SUBLIST_SIZE) {
+                final List<Integer> subList = original.subList(SUBLIST_FROM, SUBLIST_TO);
+                final List<Integer> actualSubList = new LinkedList<>();
+                subList.forEach(actualSubList::add);
+                assertEquals(actualSubList.size(), SUBLIST_SIZE);
+                for (int i = 0; i < SUBLIST_SIZE; i++) {
+                    assertEquals(actualSubList.get(i), original.get(i + SUBLIST_FROM));
+                }
+            }
+
+            trimmedSubList(list, new Callback() {
+                @Override
+                public void call(final List<Integer> list) {
+                    final List<Integer> actual = new LinkedList<>();
+                    list.forEach(actual::add);
+                    CollectionAsserts.assertContents(actual, list);
+                }
+            });
+        }
+    }
+
+    @Test
+    public void testRemoveIf() throws Exception {
+        final CollectionSupplier<List<Integer>> supplier = new CollectionSupplier((Supplier<List<Integer>>[])LIST_CLASSES, SIZE);
+        for (final CollectionSupplier.TestCase<List<Integer>> test : supplier.get()) {
+            final List<Integer> original = ((List<Integer>) test.expected);
+            final List<Integer> list = ((List<Integer>) test.collection);
+
+            try {
+                list.removeIf(null);
+                fail("expected NPE not thrown");
+            } catch (NullPointerException npe) {}
+            CollectionAsserts.assertContents(list, original);
+
+            final AtomicInteger offset = new AtomicInteger(1);
+            while (list.size() > 0) {
+                removeFirst(original, list, offset);
+            }
+        }
+
+        for (final CollectionSupplier.TestCase test : supplier.get()) {
+            final List<Integer> original = ((List<Integer>) test.expected);
+            final List<Integer> list = ((List<Integer>) test.collection);
+            list.removeIf(pOdd);
+            for (int i : list) {
+                assertTrue((i % 2) == 0);
+            }
+            for (int i : original) {
+                if (i % 2 == 0) {
+                    assertTrue(list.contains(i));
+                }
+            }
+            list.removeIf(pEven);
+            assertTrue(list.isEmpty());
+        }
+
+        for (final CollectionSupplier.TestCase test : supplier.get()) {
+            final List<Integer> original = ((List<Integer>) test.expected);
+            final List<Integer> list = ((List<Integer>) test.collection);
+            final List<Integer> listCopy = new ArrayList<>(list);
+            if (original.size() > SUBLIST_SIZE) {
+                final List<Integer> subList = list.subList(SUBLIST_FROM, SUBLIST_TO);
+                final List<Integer> subListCopy = new ArrayList<>(subList);
+                listCopy.removeAll(subList);
+                subList.removeIf(pOdd);
+                for (int i : subList) {
+                    assertTrue((i % 2) == 0);
+                }
+                for (int i : subListCopy) {
+                    if (i % 2 == 0) {
+                        assertTrue(subList.contains(i));
+                    } else {
+                        assertFalse(subList.contains(i));
+                    }
+                }
+                subList.removeIf(pEven);
+                assertTrue(subList.isEmpty());
+                // elements outside the view should remain
+                CollectionAsserts.assertContents(list, listCopy);
+            }
+        }
+
+        for (final CollectionSupplier.TestCase test : supplier.get()) {
+            final List<Integer> list = ((List<Integer>) test.collection);
+            trimmedSubList(list, new Callback() {
+                @Override
+                public void call(final List<Integer> list) {
+                    final List<Integer> copy = new ArrayList<>(list);
+                    list.removeIf(pOdd);
+                    for (int i : list) {
+                        assertTrue((i % 2) == 0);
+                    }
+                    for (int i : copy) {
+                        if (i % 2 == 0) {
+                            assertTrue(list.contains(i));
+                        } else {
+                            assertFalse(list.contains(i));
+                        }
+                    }
+                }
+            });
+        }
+    }
+
+    // remove the first element
+    private void removeFirst(final List<Integer> original, final List<Integer> list, final AtomicInteger offset) {
+        final AtomicBoolean first = new AtomicBoolean(true);
+        list.removeIf(x -> first.getAndSet(false));
+        CollectionAsserts.assertContents(original.subList(offset.getAndIncrement(), original.size()), list);
+    }
+
+    @Test
+    public void testReplaceAll() throws Exception {
+        final int scale = 3;
+        final CollectionSupplier<List<Integer>> supplier = new CollectionSupplier((Supplier<List<Integer>>[])LIST_CLASSES, SIZE);
+        for (final CollectionSupplier.TestCase<List<Integer>> test : supplier.get()) {
+            final List<Integer> original = ((List<Integer>) test.expected);
+            final List<Integer> list = ((List<Integer>) test.collection);
+
+            try {
+                list.replaceAll(null);
+                fail("expected NPE not thrown");
+            } catch (NullPointerException npe) {}
+            CollectionAsserts.assertContents(list, original);
+
+            list.replaceAll(x -> scale * x);
+            for (int i=0; i < original.size(); i++) {
+                assertTrue(list.get(i) == (scale * original.get(i)), "mismatch at index " + i);
+            }
+
+            if (original.size() > SUBLIST_SIZE) {
+                final List<Integer> subList = list.subList(SUBLIST_FROM, SUBLIST_TO);
+                subList.replaceAll(x -> x + 1);
+                // verify elements in view [from, to) were replaced
+                for (int i = 0; i < SUBLIST_SIZE; i++) {
+                    assertTrue(subList.get(i) == ((scale * original.get(i + SUBLIST_FROM)) + 1),
+                            "mismatch at sublist index " + i);
+                }
+                // verify that elements [0, from) remain unmodified
+                for (int i = 0; i < SUBLIST_FROM; i++) {
+                    assertTrue(list.get(i) == (scale * original.get(i)),
+                            "mismatch at original index " + i);
+                }
+                // verify that elements [to, size) remain unmodified
+                for (int i = SUBLIST_TO; i < list.size(); i++) {
+                    assertTrue(list.get(i) == (scale * original.get(i)),
+                            "mismatch at original index " + i);
+                }
+            }
+        }
+
+        for (final CollectionSupplier.TestCase test : supplier.get()) {
+            final List<Integer> list = ((List<Integer>) test.collection);
+            trimmedSubList(list, new Callback() {
+                @Override
+                public void call(final List<Integer> list) {
+                    final List<Integer> copy = new ArrayList<>(list);
+                    final int offset = 5;
+                    list.replaceAll(x -> offset + x);
+                    for (int i=0; i < copy.size(); i++) {
+                        assertTrue(list.get(i) == (offset + copy.get(i)), "mismatch at index " + i);
+                    }
+                }
+            });
+        }
+    }
+
+    @Test
+    public void testSort() throws Exception {
+        final CollectionSupplier<List<Integer>> supplier = new CollectionSupplier((Supplier<List<Integer>>[])LIST_CLASSES, SIZE);
+        for (final CollectionSupplier.TestCase<List<Integer>> test : supplier.get()) {
+            final List<Integer> original = ((List<Integer>) test.expected);
+            final List<Integer> list = ((List<Integer>) test.collection);
+            CollectionSupplier.shuffle(list);
+            list.sort(Integer::compare);
+            CollectionAsserts.assertSorted(list, Integer::compare);
+            if (test.name.startsWith("reverse")) {
+                Collections.reverse(list);
+            }
+            CollectionAsserts.assertContents(list, original);
+
+            CollectionSupplier.shuffle(list);
+            list.sort(null);
+            CollectionAsserts.assertSorted(list, Comparator.<Integer>naturalOrder());
+            if (test.name.startsWith("reverse")) {
+                Collections.reverse(list);
+            }
+            CollectionAsserts.assertContents(list, original);
+
+            CollectionSupplier.shuffle(list);
+            list.sort(Comparator.<Integer>naturalOrder());
+            CollectionAsserts.assertSorted(list, Comparator.<Integer>naturalOrder());
+            if (test.name.startsWith("reverse")) {
+                Collections.reverse(list);
+            }
+            CollectionAsserts.assertContents(list, original);
+
+            CollectionSupplier.shuffle(list);
+            list.sort(Comparator.<Integer>reverseOrder());
+            CollectionAsserts.assertSorted(list, Comparator.<Integer>reverseOrder());
+            if (!test.name.startsWith("reverse")) {
+                Collections.reverse(list);
+            }
+            CollectionAsserts.assertContents(list, original);
+
+            CollectionSupplier.shuffle(list);
+            list.sort(BIT_COUNT_COMPARATOR);
+            CollectionAsserts.assertSorted(list, BIT_COUNT_COMPARATOR);
+            // check sort by verifying that bitCount increases and never drops
+            int minBitCount = 0;
+            int bitCount = 0;
+            for (final Integer i : list) {
+                bitCount = Integer.bitCount(i);
+                assertTrue(bitCount >= minBitCount);
+                minBitCount = bitCount;
+            }
+
+            @SuppressWarnings("unchecked")
+            final Constructor<? extends List<?>> defaultConstructor = ((Class<? extends List<?>>)test.collection.getClass()).getConstructor();
+            final List<AtomicInteger> incomparables = (List<AtomicInteger>) defaultConstructor.newInstance();
+
+            for (int i=0; i < test.expected.size(); i++) {
+                incomparables.add(new AtomicInteger(i));
+            }
+            CollectionSupplier.shuffle(incomparables);
+            incomparables.sort(ATOMIC_INTEGER_COMPARATOR);
+            for (int i=0; i < test.expected.size(); i++) {
+                assertEquals(i, incomparables.get(i).intValue());
+            }
+
+            if (original.size() > SUBLIST_SIZE) {
+                final List<Integer> copy = new ArrayList<>(list);
+                final List<Integer> subList = list.subList(SUBLIST_FROM, SUBLIST_TO);
+                CollectionSupplier.shuffle(subList);
+                subList.sort(Comparator.<Integer>naturalOrder());
+                CollectionAsserts.assertSorted(subList, Comparator.<Integer>naturalOrder());
+                // verify that elements [0, from) remain unmodified
+                for (int i = 0; i < SUBLIST_FROM; i++) {
+                    assertTrue(list.get(i) == copy.get(i),
+                            "mismatch at index " + i);
+                }
+                // verify that elements [to, size) remain unmodified
+                for (int i = SUBLIST_TO; i < list.size(); i++) {
+                    assertTrue(list.get(i) == copy.get(i),
+                            "mismatch at index " + i);
+                }
+            }
+        }
+
+        for (final CollectionSupplier.TestCase test : supplier.get()) {
+            final List<Integer> list = ((List<Integer>) test.collection);
+            trimmedSubList(list, new Callback() {
+                @Override
+                public void call(final List<Integer> list) {
+                    final List<Integer> copy = new ArrayList<>(list);
+                    CollectionSupplier.shuffle(list);
+                    list.sort(Comparator.<Integer>naturalOrder());
+                    CollectionAsserts.assertSorted(list, Comparator.<Integer>naturalOrder());
+                }
+            });
+        }
+    }
+
+    @Test
+    public void testForEachThrowsCME() throws Exception {
+        final CollectionSupplier<List<Integer>> supplier = new CollectionSupplier((Supplier<List<Integer>>[])LIST_CME_CLASSES, SIZE);
+        for (final CollectionSupplier.TestCase<List<Integer>> test : supplier.get()) {
+            final List<Integer> list = ((List<Integer>) test.collection);
+
+            if (list.size() <= 1) {
+                continue;
+            }
+            boolean gotException = false;
+            try {
+                // bad predicate that modifies its list, should throw CME
+                list.forEach((x) -> {list.add(x);});
+            } catch (ConcurrentModificationException cme) {
+                gotException = true;
+            }
+            if (!gotException) {
+                fail("expected CME was not thrown from " + test);
+            }
+        }
+    }
+
+    @Test
+    public void testRemoveIfThrowsCME() throws Exception {
+        final CollectionSupplier<List<Integer>> supplier = new CollectionSupplier((Supplier<List<Integer>>[])LIST_CME_CLASSES, SIZE);
+        for (final CollectionSupplier.TestCase<List<Integer>> test : supplier.get()) {
+            final List<Integer> original = ((List<Integer>) test.expected);
+            final List<Integer> list = ((List<Integer>) test.collection);
+
+            if (list.size() <= 1) {
+                continue;
+            }
+            boolean gotException = false;
+            try {
+                // bad predicate that modifies its list, should throw CME
+                list.removeIf((x) -> {return list.add(x);});
+            } catch (ConcurrentModificationException cme) {
+                gotException = true;
+            }
+            if (!gotException) {
+                fail("expected CME was not thrown from " + test);
+            }
+        }
+    }
+
+    @Test
+    public void testReplaceAllThrowsCME() throws Exception {
+        final CollectionSupplier<List<Integer>> supplier = new CollectionSupplier((Supplier<List<Integer>>[])LIST_CME_CLASSES, SIZE);
+        for (final CollectionSupplier.TestCase<List<Integer>> test : supplier.get()) {
+            final List<Integer> list = ((List<Integer>) test.collection);
+
+            if (list.size() <= 1) {
+                continue;
+            }
+            boolean gotException = false;
+            try {
+                // bad predicate that modifies its list, should throw CME
+                list.replaceAll(x -> {int n = 3 * x; list.add(n); return n;});
+            } catch (ConcurrentModificationException cme) {
+                gotException = true;
+            }
+            if (!gotException) {
+                fail("expected CME was not thrown from " + test);
+            }
+        }
+    }
+
+    @Test
+    public void testSortThrowsCME() throws Exception {
+        final CollectionSupplier<List<Integer>> supplier = new CollectionSupplier((Supplier<List<Integer>>[])LIST_CME_CLASSES, SIZE);
+        for (final CollectionSupplier.TestCase<List<Integer>> test : supplier.get()) {
+            final List<Integer> list = ((List<Integer>) test.collection);
+
+            if (list.size() <= 1) {
+                continue;
+            }
+            boolean gotException = false;
+            try {
+                // bad predicate that modifies its list, should throw CME
+                list.sort((x, y) -> {list.add(x); return x - y;});
+            } catch (ConcurrentModificationException cme) {
+                gotException = true;
+            }
+            if (!gotException) {
+                fail("expected CME was not thrown from " + test);
+            }
+        }
+    }
+
+    private static final List<Integer> SLICED_EXPECTED = Arrays.asList(0, 1, 2, 3, 5, 6, 7, 8, 9);
+    private static final List<Integer> SLICED_EXPECTED2 = Arrays.asList(0, 1, 2, 5, 6, 7, 8, 9);
+
+    @DataProvider(name="shortIntListProvider", parallel=true)
+    public static Object[][] intListCases() {
+        final Integer[] DATA = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+        final List<Object[]> cases = new LinkedList<>();
+        cases.add(new Object[] { new ArrayList<>(Arrays.asList(DATA)) });
+        cases.add(new Object[] { new LinkedList<>(Arrays.asList(DATA)) });
+        cases.add(new Object[] { new Vector<>(Arrays.asList(DATA)) });
+        cases.add(new Object[] { new CopyOnWriteArrayList<>(Arrays.asList(DATA)) });
+        cases.add(new Object[] { new ExtendsAbstractList<>(Arrays.asList(DATA)) });
+        return cases.toArray(new Object[0][cases.size()]);
+    }
+
+    @Test(dataProvider = "shortIntListProvider")
+    public void testRemoveIfFromSlice(final List<Integer> list) throws Exception {
+        final List<Integer> sublist = list.subList(3, 6);
+        assertTrue(sublist.removeIf(x -> x == 4));
+        CollectionAsserts.assertContents(list, SLICED_EXPECTED);
+
+        final List<Integer> sublist2 = list.subList(2, 5);
+        assertTrue(sublist2.removeIf(x -> x == 3));
+        CollectionAsserts.assertContents(list, SLICED_EXPECTED2);
+    }
+}
--- a/test/java/util/Map/Defaults.java	Fri Sep 13 12:20:53 2013 +0100
+++ b/test/java/util/Map/Defaults.java	Fri Sep 13 11:18:44 2013 -0700
@@ -155,7 +155,7 @@
         assertThrows(
             () -> { map.replaceAll((k,v) -> null); },
             NullPointerException.class,
-            description);
+            description + " should not allow replacement with null value");
     }
 
     @Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=withNull values=withNull")
@@ -194,6 +194,15 @@
         assertSame(map.get(null), EXTRA_VALUE);
     }
 
+    @Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=nonNull values=nonNull")
+    public void testReplaceKVNoNulls(String description, Map<IntegerEnum, String> map) {
+        assertTrue(map.containsKey(FIRST_KEY), "expected key missing");
+        assertSame(map.get(FIRST_KEY), FIRST_VALUE, "found wrong value");
+        assertThrows( () -> {map.replace(FIRST_KEY, null);}, NullPointerException.class, description + ": should throw NPE");
+        assertSame(map.replace(FIRST_KEY, EXTRA_VALUE), FIRST_VALUE, description + ": replaced wrong value");
+        assertSame(map.get(FIRST_KEY), EXTRA_VALUE, "found wrong value");
+    }
+
     @Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=all values=all")
     public void testReplaceKV(String description, Map<IntegerEnum, String> map) {
         assertTrue(map.containsKey(KEYS[1]));
@@ -224,6 +233,16 @@
         assertSame(map.get(null), EXTRA_VALUE);
     }
 
+    @Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=nonNull values=nonNull")
+    public void testReplaceKVVNoNulls(String description, Map<IntegerEnum, String> map) {
+        assertTrue(map.containsKey(FIRST_KEY), "expected key missing");
+        assertSame(map.get(FIRST_KEY), FIRST_VALUE, "found wrong value");
+        assertThrows( () -> {map.replace(FIRST_KEY, FIRST_VALUE, null);}, NullPointerException.class, description + ": should throw NPE");
+        assertThrows( () -> {if (!map.replace(FIRST_KEY, null, EXTRA_VALUE)) throw new NullPointerException("default returns false rather than throwing");}, NullPointerException.class,  description + ": should throw NPE");
+        assertTrue(map.replace(FIRST_KEY, FIRST_VALUE, EXTRA_VALUE), description + ": replaced wrong value");
+        assertSame(map.get(FIRST_KEY), EXTRA_VALUE, "found wrong value");
+    }
+
     @Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=all values=all")
     public void testReplaceKVV(String description, Map<IntegerEnum, String> map) {
         assertTrue(map.containsKey(KEYS[1]));
@@ -470,6 +489,9 @@
             VALUES[each] = String.valueOf(each);
         }
     }
+
+    private static final IntegerEnum FIRST_KEY = KEYS[0];
+    private static final String FIRST_VALUE = VALUES[0];
     private static final IntegerEnum EXTRA_KEY = IntegerEnum.EXTRA_KEY;
     private static final String EXTRA_VALUE = String.valueOf(TEST_SIZE);
 
@@ -583,6 +605,8 @@
         return Arrays.asList(
                 // null key hostile
                 new Object[]{"EnumMap", makeMap(() -> new EnumMap(IntegerEnum.class), false, nulls)},
+                new Object[]{"TreeMap", makeMap(TreeMap::new, false, nulls)},
+                new Object[]{"ExtendsAbstractMap(TreeMap)", makeMap(() -> {return new ExtendsAbstractMap(new TreeMap());}, false, nulls)},
                 new Object[]{"Collections.synchronizedMap(EnumMap)", Collections.synchronizedMap(makeMap(() -> new EnumMap(IntegerEnum.class), false, nulls))}
                 );
     }
@@ -591,10 +615,11 @@
         return Arrays.asList(
             // null key and value hostile
             new Object[]{"Hashtable", makeMap(Hashtable::new, false, false)},
-            new Object[]{"TreeMap", makeMap(TreeMap::new, false, false)},
             new Object[]{"ConcurrentHashMap", makeMap(ConcurrentHashMap::new, false, false)},
             new Object[]{"ConcurrentSkipListMap", makeMap(ConcurrentSkipListMap::new, false, false)},
+            new Object[]{"Collections.synchronizedMap(ConcurrentHashMap)", Collections.synchronizedMap(makeMap(ConcurrentHashMap::new, false, false))},
             new Object[]{"Collections.checkedMap(ConcurrentHashMap)", Collections.checkedMap(makeMap(ConcurrentHashMap::new, false, false), IntegerEnum.class, String.class)},
+            new Object[]{"ExtendsAbstractMap(ConcurrentHashMap)", makeMap(() -> {return new ExtendsAbstractMap(new ConcurrentHashMap());}, false, false)},
             new Object[]{"ImplementsConcurrentMap", makeMap(ImplementsConcurrentMap::new, false, false)}
             );
     }
@@ -641,18 +666,17 @@
     }
 
     public static <T extends Throwable> void assertThrows(Thrower<T> thrower, Class<T> throwable, String message) {
-        Throwable result;
+        Throwable thrown;
         try {
             thrower.run();
-            result = null;
+            thrown = null;
         } catch (Throwable caught) {
-            result = caught;
+            thrown = caught;
         }
 
-        assertInstance(result, throwable,
-            (null != message)
-            ? message
-            : "Failed to throw " + throwable.getCanonicalName());
+        assertInstance(thrown, throwable,
+            ((null != message) ? message : "") +
+            " Failed to throw " + throwable.getCanonicalName());
     }
 
     public static <T extends Throwable> void assertThrows(Class<T> throwable, String message, Thrower<T>... throwers) {
@@ -661,11 +685,11 @@
         }
     }
 
-    public static <T> void assertInstance(T actual, Class<? extends T> expected) {
+    public static void assertInstance(Object actual, Class<?> expected) {
         assertInstance(expected.isInstance(actual), null);
     }
 
-    public static <T> void assertInstance(T actual, Class<? extends T> expected, String message) {
+    public static void assertInstance(Object actual, Class<?> expected, String message) {
         assertTrue(expected.isInstance(actual), message);
     }