You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by te...@apache.org on 2009/06/16 11:20:10 UTC

svn commit: r785120 - in /harmony/enhanced/classlib/trunk/modules/luni/src: main/java/java/util/ArrayList.java test/api/common/org/apache/harmony/luni/tests/java/util/ArrayListTest.java

Author: tellison
Date: Tue Jun 16 09:20:09 2009
New Revision: 785120

URL: http://svn.apache.org/viewvc?rev=785120&view=rev
Log:
Apply patch HARMONY-6236 ([classlib][luni] ArrayList breaks when given concurrent collections as input)

Modified:
    harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/util/ArrayList.java
    harmony/enhanced/classlib/trunk/modules/luni/src/test/api/common/org/apache/harmony/luni/tests/java/util/ArrayListTest.java

Modified: harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/util/ArrayList.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/util/ArrayList.java?rev=785120&r1=785119&r2=785120&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/util/ArrayList.java (original)
+++ harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/util/ArrayList.java Tue Jun 16 09:20:09 2009
@@ -73,10 +73,11 @@
      *            the collection of elements to add.
      */
     public ArrayList(Collection<? extends E> collection) {
-        int size = collection.size();
         firstIndex = 0;
+        Object[] objects = collection.toArray();
+        int size = objects.length;
         array = newElementArray(size + (size / 10));
-        collection.toArray(array);
+        System.arraycopy(objects, 0, array, 0, size);
         lastIndex = size;
         modCount = 1;
     }
@@ -173,7 +174,12 @@
         if (this == collection) {
             collection = (ArrayList)clone();
         }
-        int growSize = collection.size();
+        Object[] dumparray = collection.toArray();
+        int growSize = dumparray.length;
+        if (growSize == 0) {
+            return false;
+        }
+
         if (0 < location && location < size) {
             if (array.length - size < growSize) {
                 growForInsert(location, growSize);
@@ -205,15 +211,10 @@
             lastIndex += growSize;
         }
 
-        if (growSize > 0) {
-            Object[] dumparray = new Object[growSize];
-            collection.toArray(dumparray);
-            System.arraycopy(dumparray, 0, this.array, location + firstIndex,
-                    growSize);
-            modCount++;
-            return true;
-        }
-        return false;
+        System.arraycopy(dumparray, 0, this.array, location + firstIndex,
+                growSize);
+        modCount++;
+        return true;
     }
 
     /**

Modified: harmony/enhanced/classlib/trunk/modules/luni/src/test/api/common/org/apache/harmony/luni/tests/java/util/ArrayListTest.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/luni/src/test/api/common/org/apache/harmony/luni/tests/java/util/ArrayListTest.java?rev=785120&r1=785119&r2=785120&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/luni/src/test/api/common/org/apache/harmony/luni/tests/java/util/ArrayListTest.java (original)
+++ harmony/enhanced/classlib/trunk/modules/luni/src/test/api/common/org/apache/harmony/luni/tests/java/util/ArrayListTest.java Tue Jun 16 09:20:09 2009
@@ -86,6 +86,12 @@
 
     }
 
+    public void testConstructorWithConcurrentCollection() {
+        Collection<String> collection = shrinksOnSize("A", "B", "C", "D");
+        ArrayList<String> list = new ArrayList<String>(collection);
+        assertFalse(list.contains(null));
+    }
+
     /**
      * @tests java.util.ArrayList#add(int, java.lang.Object)
      */
@@ -866,6 +872,20 @@
         assertEquals(14, list.size());
     }
 
+    public void testAddAllWithConcurrentCollection() {
+        ArrayList<String> list = new ArrayList<String>();
+        list.addAll(shrinksOnSize("A", "B", "C", "D"));
+        assertFalse(list.contains(null));
+    }
+
+    public void testAddAllAtPositionWithConcurrentCollection() {
+        ArrayList<String> list = new ArrayList<String>(
+                Arrays.asList("A", "B", "C", "D"));
+
+        list.addAll(3, shrinksOnSize("E", "F", "G", "H"));
+        assertFalse(list.contains(null));
+    }
+
     public void test_override_size() throws Exception {
         ArrayList testlist = new MockArrayList();
         // though size is overriden, it should passed without exception
@@ -927,4 +947,31 @@
         for (int i = 0; i < objArray.length; i++)
             alist.add(objArray[i]);
     }
+
+    /**
+     * Returns a collection that emulates another thread calling remove() each
+     * time the current thread calls size().
+     */
+    private <T> Collection<T> shrinksOnSize(T... elements) {
+        return new HashSet<T>(Arrays.asList(elements)) {
+            boolean shrink = true;
+
+            @Override
+            public int size() {
+                int result = super.size();
+                if (shrink) {
+                    Iterator<T> i = iterator();
+                    i.next();
+                    i.remove();
+                }
+                return result;
+            }
+
+            @Override
+            public Object[] toArray() {
+                shrink = false;
+                return super.toArray();
+            }
+        };
+    }
 }