Fix incorrect size calculated by EnumSet.of(varargs) in web mode.

Review by: scottb



git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@5876 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/super/com/google/gwt/emul/java/util/EnumSet.java b/user/super/com/google/gwt/emul/java/util/EnumSet.java
index e0cc934..51c24f1 100644
--- a/user/super/com/google/gwt/emul/java/util/EnumSet.java
+++ b/user/super/com/google/gwt/emul/java/util/EnumSet.java
@@ -229,10 +229,15 @@
     E[] all = first.getDeclaringClass().getEnumConstants();
     E[] set = Array.createFrom(all);
     set[first.ordinal()] = first;
+    int size = 1;
     for (E e : rest) {
-      set[e.ordinal()] = e;
+      int ordinal = e.ordinal();
+      if (set[ordinal] == null) {
+        set[ordinal] = e;
+        ++size; // count only new elements
+      }
     }
-    return new EnumSetImpl<E>(all, set, rest.length + 1);
+    return new EnumSetImpl<E>(all, set, size);
   }
 
   public static <E extends Enum<E>> EnumSet<E> range(E from, E to) {
diff --git a/user/test/com/google/gwt/emultest/java/util/EnumSetTest.java b/user/test/com/google/gwt/emultest/java/util/EnumSetTest.java
index 07b9104..f709525 100644
--- a/user/test/com/google/gwt/emultest/java/util/EnumSetTest.java
+++ b/user/test/com/google/gwt/emultest/java/util/EnumSetTest.java
@@ -22,6 +22,7 @@
 import java.util.List;
 import java.util.ArrayList;
 import java.util.EnumSet;
+import java.util.NoSuchElementException;
 
 /**
  * Tests EnumSet. TODO(tobyr) Consider using Apache collections tests.
@@ -39,6 +40,32 @@
   public String getModuleName() {
     return "com.google.gwt.emultest.EmulSuite";
   }
+  
+  /**
+   * Test failure mode from issue 3605.  Previously resulted in an incorrect size.
+   */
+  public void testDuplicates() {
+    EnumSet<Numbers> set = EnumSet.of(Numbers.Two, Numbers.One, Numbers.Two, Numbers.One);
+    assertEquals(set.size(), 2);
+    assertTrue(set.contains(Numbers.One));
+    assertTrue(set.contains(Numbers.Two));
+  }
+  
+  /**
+   * Test failure mode from issue 3605.  Previously resulted in a NoSuchElementException.
+   */
+  public void testDuplicatesToArray() {
+    EnumSet<Numbers> set = EnumSet.of(Numbers.Two, Numbers.One, Numbers.Two, Numbers.One);
+    Numbers[] array = set.toArray(new Numbers[set.size()]);
+    assertNotNull(array);
+    assertEquals(array.length, 2);
+    if (array[0] != Numbers.One && array[1] != Numbers.One) {
+      fail("Numbers.One not found");
+    }
+    if (array[0] != Numbers.Two && array[1] != Numbers.Two) {
+      fail("Numbers.Two not found");
+    }
+  }
 
   public void testNumbers() {
     enumTest(Numbers.class);
@@ -77,9 +104,14 @@
     assertEquals(numberSet, numbers);
 
     // Attempt to add a duplicate value
+    int numbersSize = numbers.size();
+    int numberSetSize = numberSet.size();
     numbers.add(enums[23]);
     numberSet.add(enums[23]);
     assertEquals(numberSet, numbers);
+    // Check sizes haven't changed
+    assertEquals(numbersSize, numbers.size());
+    assertEquals(numberSetSize, numberSet.size());
 
     numbers = EnumSet.allOf(e);
     numberSet.clear();