Fix System.arrayCopy to handle interfaces properly.

Issue: 3621
Patch by: hayward.chan
Review by: jat


git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@7286 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/super/com/google/gwt/emul/java/lang/System.java b/user/super/com/google/gwt/emul/java/lang/System.java
index 8567ef6..333b5b2 100644
--- a/user/super/com/google/gwt/emul/java/lang/System.java
+++ b/user/super/com/google/gwt/emul/java/lang/System.java
@@ -52,8 +52,7 @@
 
     Class<?> srcComp = srcType.getComponentType();
     Class<?> destComp = destType.getComponentType();
-    if (srcComp.modifiers != destComp.modifiers
-        || (srcComp.isPrimitive() && !srcComp.equals(destComp))) {
+    if (!arrayTypeMatch(srcComp, destComp)) {
       throw new ArrayStoreException("Array types must match");
     }
     int srclen = getArrayLength(src);
@@ -92,7 +91,7 @@
 
   public static long currentTimeMillis() {
     return (long) currentTimeMillis0();
-  };
+  }
 
   /**
    * Has no effect; just here for source compatibility.
@@ -100,7 +99,7 @@
    * @skip
    */
   public static void gc() {
-  };
+  }
 
   public static int identityHashCode(Object o) {
     return (o == null) ? 0 : (!(o instanceof String)) ? Impl.getHashCode(o)
@@ -115,6 +114,14 @@
     @java.lang.System::out = out;
   }-*/;
 
+  private static boolean arrayTypeMatch(Class<?> srcComp, Class<?> destComp) {
+    if (srcComp.isPrimitive()) {
+      return srcComp.equals(destComp);
+    } else {
+      return !destComp.isPrimitive();
+    }
+  }
+
   private static native double currentTimeMillis0() /*-{
     return (new Date()).getTime();
   }-*/;
diff --git a/user/test/com/google/gwt/emultest/java/lang/SystemTest.java b/user/test/com/google/gwt/emultest/java/lang/SystemTest.java
index 5df9bb0..dab692a 100644
--- a/user/test/com/google/gwt/emultest/java/lang/SystemTest.java
+++ b/user/test/com/google/gwt/emultest/java/lang/SystemTest.java
@@ -17,6 +17,8 @@
 
 import com.google.gwt.junit.client.GWTTestCase;
 
+import java.util.Arrays;
+
 /**
  * Tests java.lang.System.
  */
@@ -27,15 +29,75 @@
     }
   }
 
+  private enum EnumImpl implements Interfaz {
+    FOO,
+    BAR,
+    BAZ
+  }
+
   private static class Foo {
     public Foo() {
     }
   }
 
+  private interface Interfaz {
+  }
+
+  private static class InterfazImpl implements Interfaz {
+
+    private final String data;
+
+    /**
+     * @param data non-null string
+     */
+    InterfazImpl(String data) {
+      this.data = data;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+      return (obj instanceof InterfazImpl) && ((InterfazImpl) obj).data.equals(
+          data);
+    }
+
+    @Override
+    public int hashCode() {
+      return data.hashCode();
+    }
+
+    @Override
+    public String toString() {
+      return "InterfazImpl[data=" + data + "]";
+    }
+  }
+
+  @Override
   public String getModuleName() {
     return "com.google.gwt.emultest.EmulSuite";
   }
 
+  public void testArraycopyEnumToInterface() {
+    EnumImpl[] src = new EnumImpl[]{ EnumImpl.FOO, null, EnumImpl.BAZ };
+    Interfaz[] dest = new Interfaz[5];
+    Arrays.fill(dest, null);  // undefined != null, wierd.
+
+    System.arraycopy(src, 0, dest, 1, 3);
+    assertEquals(
+        Arrays.asList(null, EnumImpl.FOO, null, EnumImpl.BAZ, null),
+        Arrays.asList(dest));
+  }
+
+  public void testArraycopyEnumToObject() {
+    EnumImpl[] src = new EnumImpl[]{ EnumImpl.FOO, null, EnumImpl.BAZ };
+    Object[] dest = new Object[5];
+    Arrays.fill(dest, null);  // undefined != null, wierd.
+
+    System.arraycopy(src, 0, dest, 1, 3);
+    assertEquals(
+        Arrays.asList(null, EnumImpl.FOO, null, EnumImpl.BAZ, null),
+        Arrays.asList(dest));
+  }
+
   public void testArraycopyFailures() {
     int[] src = new int[4];
     int[] dest = new int[] {1, 1, 1, 1};
@@ -93,6 +155,17 @@
     }
   }
 
+  public void testArraycopyInterfaceToObject() {
+    Interfaz[] src = new Interfaz[]{
+        new InterfazImpl("foo"), null, new InterfazImpl("bar") };
+    Object[] dest = new Object[5];
+    Arrays.fill(dest, null);  // undefined != null, wierd.
+
+    System.arraycopy(src, 0, dest, 1, 3);
+    assertEquals(Arrays.asList(null, new InterfazImpl("foo"), null,
+        new InterfazImpl("bar"), null), Arrays.asList(dest));
+  }
+
   public void testArraycopyMultidim() {
     Object[][] objArray = new Object[1][1];
     String[][] strArray = new String[1][1];
@@ -151,7 +224,7 @@
       assertNull(barArray[3]);
     }
   }
-
+  
   public void testArraycopyOverlap() {
     int[] intArray = new int[] {0, 1, 2, 3};
     String[] strArray = new String[] {"0", "1", "2", "3"};
@@ -165,18 +238,21 @@
     for (int i = 0; i < intArray.length - 1; ++i) {
       assertEquals("fwd int copy index " + i, i, intArray[i]);
     }
-    assertEquals("fwd int copy index " + (intArray.length - 2), intArray.length - 2,
-        intArray[intArray.length - 1]);
+    assertEquals("fwd int copy index " + (intArray.length - 2),
+        intArray.length - 2, intArray[intArray.length - 1]);
     System.arraycopy(strArray, 0, strArray, 1, strArray.length - 1);
     assertEquals(0, Integer.valueOf(strArray[0]).intValue());
     for (int i = 1; i < strArray.length; ++i) {
-      assertEquals("rev str copy index " + i, i - 1, Integer.valueOf(strArray[i]).intValue());
+      assertEquals("rev str copy index " + i, i - 1, Integer.valueOf(
+          strArray[i]).intValue());
     }
     System.arraycopy(strArray, 1, strArray, 0, strArray.length - 1);
     for (int i = 0; i < strArray.length - 1; ++i) {
-      assertEquals("fwd str copy index " + i, i, Integer.valueOf(strArray[i]).intValue());
+      assertEquals("fwd str copy index " + i, i, Integer.valueOf(
+          strArray[i]).intValue());
     }
-    assertEquals("fwd str copy index " + (strArray.length - 2), strArray.length - 2,
+    assertEquals("fwd str copy index " + (strArray.length - 2),
+        strArray.length - 2,
         Integer.valueOf(strArray[strArray.length - 1]).intValue());
     /*
      * TODO(jat): how is it supposed to behave with overlapped copies if there