Widening/Narrowing opertaions in j.l.reflect.Array.

Adds correct narrowing and widening operations in
Array.java.

Change-Id: I8583263f7142337143709cf006c1033b5dadcd47
Review-Link: https://gwt-review.googlesource.com/#/c/19300/
diff --git a/user/super/com/google/gwt/emul/java/lang/reflect/Array.java b/user/super/com/google/gwt/emul/java/lang/reflect/Array.java
index f9a3a6c..4695ebc 100644
--- a/user/super/com/google/gwt/emul/java/lang/reflect/Array.java
+++ b/user/super/com/google/gwt/emul/java/lang/reflect/Array.java
@@ -82,8 +82,24 @@
   }
 
   public static double getDouble(Object array, int index) {
-    checkArgument(array instanceof double[]);
-    return getDoubleImpl(array, index);
+    if (array instanceof double[]) {
+      return getDoubleImpl(array, index);
+    } else if (array instanceof byte[]) {
+      return getByteImpl(array, index);
+    } else if (array instanceof char[]) {
+      return getCharImpl(array, index);
+    } else if (array instanceof float[]) {
+      return getFloatImpl(array, index);
+    } else if (array instanceof int[]) {
+      return getIntImpl(array, index);
+    } else if (array instanceof long[]) {
+      return getLongImpl(array, index);
+    } else if (array instanceof short[]) {
+      return getShortImpl(array, index);
+    } else {
+      checkArgument(false);
+      return 0;
+    }
   }
 
   private static double getDoubleImpl(Object array, int index) {
@@ -92,8 +108,22 @@
   }
 
   public static float getFloat(Object array, int index) {
-    checkArgument(array instanceof float[]);
-    return getFloatImpl(array, index);
+    if (array instanceof float[]) {
+      return getFloatImpl(array, index);
+    } else if (array instanceof byte[]) {
+      return getByteImpl(array, index);
+    } else if (array instanceof char[]) {
+      return getCharImpl(array, index);
+    } else if (array instanceof int[]) {
+      return getIntImpl(array, index);
+    } else if (array instanceof long[]) {
+      return getLongImpl(array, index);
+    } else if (array instanceof short[]) {
+      return getShortImpl(array, index);
+    } else {
+      checkArgument(false);
+      return 0;
+    }
   }
 
   private static float getFloatImpl(Object array, int index) {
@@ -102,8 +132,18 @@
   }
 
   public static int getInt(Object array, int index) {
-    checkArgument(array instanceof int[]);
-    return getIntImpl(array, index);
+    if (array instanceof int[]) {
+      return getIntImpl(array, index);
+    } else if (array instanceof byte[]) {
+      return getByteImpl(array, index);
+    } else if (array instanceof char[]) {
+      return getCharImpl(array, index);
+    } else if (array instanceof short[]) {
+      return getShortImpl(array, index);
+    } else {
+      checkArgument(false);
+      return 0;
+    }
   }
 
   private static int getIntImpl(Object array, int index) {
@@ -117,8 +157,20 @@
   }
 
   public static long getLong(Object array, int index) {
-    checkArgument(array instanceof long[]);
-    return getLongImpl(array, index);
+    if (array instanceof long[]) {
+      return getLongImpl(array, index);
+    } else if (array instanceof byte[]) {
+      return getByteImpl(array, index);
+    } else if (array instanceof char[]) {
+      return getCharImpl(array, index);
+    } else if (array instanceof int[]) {
+      return getIntImpl(array, index);
+    } else if (array instanceof short[]) {
+      return getShortImpl(array, index);
+    } else {
+      checkArgument(false);
+      return 0;
+    }
   }
 
   private static long getLongImpl(Object array, int index) {
@@ -127,8 +179,14 @@
   }
 
   public static short getShort(Object array, int index) {
-    checkArgument(array instanceof short[]);
-    return getShortImpl(array, index);
+    if (array instanceof short[]) {
+      return getShortImpl(array, index);
+    } else if (array instanceof byte[]) {
+      return getByteImpl(array, index);
+    } else {
+      checkArgument(false);
+      return 0;
+    }
   }
 
   private static short getShortImpl(Object array, int index) {
@@ -137,26 +195,29 @@
   }
 
   public static void set(Object array, int index, Object value) {
-    if (array instanceof boolean[]) {
-      setBooleanImpl(array, index, (Boolean) value);
-    } else if (array instanceof byte[]) {
-      setByteImpl(array, index, (Byte) value);
-    } else if (array instanceof char[]) {
-      setCharImpl(array, index, (Character) value);
-    } else if (array instanceof double[]) {
-      setDoubleImpl(array, index, (Double) value);
-    } else if (array instanceof float[]) {
-      setFloatImpl(array, index, (Float) value);
-    } else if (array instanceof int[]) {
-      setIntImpl(array, index, (Integer) value);
-    } else if (array instanceof long[]) {
-      setLongImpl(array, index, (Long) value);
-    } else if (array instanceof short[]) {
-      setShortImpl(array, index, (Short) value);
-    } else {
-      checkArgument(array instanceof Object[]);
+    if (array instanceof Object[]) {
       Object[] typedArray = (Object[]) array;
       typedArray[index] = value;
+    } else {
+      if (value instanceof Boolean) {
+        setBoolean(array, index, ((Boolean) value).booleanValue());
+      } else if (value instanceof Byte) {
+        setByte(array, index, ((Byte) value).byteValue());
+      } else if (value instanceof Character) {
+        setChar(array, index, ((Character) value).charValue());
+      } else if (value instanceof Short) {
+        setShort(array, index, ((Short) value).shortValue());
+      } else if (value instanceof Integer) {
+        setInt(array, index, ((Integer) value).intValue());
+      } else if (value instanceof Long) {
+        setLong(array, index, ((Long) value).longValue());
+      } else if (value instanceof Float) {
+        setFloat(array, index, ((Float) value).floatValue());
+      } else if (value instanceof Double) {
+        setDouble(array, index, ((Double) value).doubleValue());
+      } else {
+        checkArgument(false);
+      }
     }
   }
 
@@ -171,8 +232,21 @@
   }
 
   public static void setByte(Object array, int index, byte value) {
-    checkArgument(array instanceof byte[]);
-    setByteImpl(array, index, value);
+    if (array instanceof byte[]) {
+      setByteImpl(array, index, value);
+    } else if (array instanceof double[]) {
+      setDoubleImpl(array, index, value);
+    } else if (array instanceof float[]) {
+      setFloatImpl(array, index, value);
+    } else if (array instanceof int[]) {
+      setIntImpl(array, index, value);
+    } else if (array instanceof long[]) {
+      setLongImpl(array, index, value);
+    } else if (array instanceof short[]) {
+      setShortImpl(array, index, value);
+    } else {
+      checkArgument(false);
+    }
   }
 
   private static void setByteImpl(Object array, int index, byte value) {
@@ -181,8 +255,19 @@
   }
 
   public static void setChar(Object array, int index, char value) {
-    checkArgument(array instanceof char[]);
-    setCharImpl(array, index, value);
+    if (array instanceof char[]) {
+      setCharImpl(array, index, value);
+    } else if (array instanceof double[]) {
+      setDoubleImpl(array, index, value);
+    } else if (array instanceof float[]) {
+      setFloatImpl(array, index, value);
+    } else if (array instanceof int[]) {
+      setIntImpl(array, index, value);
+    } else if (array instanceof long[]) {
+      setLongImpl(array, index, value);
+    } else {
+      checkArgument(false);
+    }
   }
 
   private static void setCharImpl(Object array, int index, char value) {
@@ -201,8 +286,13 @@
   }
 
   public static void setFloat(Object array, int index, float value) {
-    checkArgument(array instanceof float[]);
-    setFloatImpl(array, index, value);
+    if (array instanceof float[]) {
+      setFloatImpl(array, index, value);
+    } else if (array instanceof double[]) {
+      setDoubleImpl(array, index, value);
+    } else {
+      checkArgument(false);
+    }
   }
 
   private static void setFloatImpl(Object array, int index, float value) {
@@ -211,8 +301,17 @@
   }
 
   public static void setInt(Object array, int index, int value) {
-    checkArgument(array instanceof int[]);
-    setIntImpl(array, index, value);
+    if (array instanceof int[]) {
+      setIntImpl(array, index, value);
+    } else if (array instanceof double[]) {
+      setDoubleImpl(array, index, value);
+    } else if (array instanceof float[]) {
+      setFloatImpl(array, index, value);
+    } else if (array instanceof long[]) {
+      setLongImpl(array, index, value);
+    } else {
+      checkArgument(false);
+    }
   }
 
   private static void setIntImpl(Object array, int index, int value) {
@@ -221,8 +320,15 @@
   }
 
   public static void setLong(Object array, int index, long value) {
-    checkArgument(array instanceof long[]);
-    setLongImpl(array, index, value);
+    if (array instanceof long[]) {
+      setLongImpl(array, index, value);
+    } else if (array instanceof double[]) {
+      setDoubleImpl(array, index, value);
+    } else if (array instanceof float[]) {
+      setFloatImpl(array, index, value);
+    } else {
+      checkArgument(false);
+    }
   }
 
   private static void setLongImpl(Object array, int index, long value) {
@@ -231,8 +337,19 @@
   }
 
   public static void setShort(Object array, int index, short value) {
-    checkArgument(array instanceof short[]);
-    setShortImpl(array, index, value);
+    if (array instanceof short[]) {
+      setShortImpl(array, index, value);
+    } else if (array instanceof double[]) {
+      setDoubleImpl(array, index, value);
+    } else if (array instanceof float[]) {
+      setFloatImpl(array, index, value);
+    } else if (array instanceof int[]) {
+      setIntImpl(array, index, value);
+    } else if (array instanceof long[]) {
+      setLongImpl(array, index, value);
+    } else {
+      checkArgument(false);
+    }
   }
 
   private static void setShortImpl(Object array, int index, short value) {
diff --git a/user/test/com/google/gwt/emultest/java/lang/reflect/ArrayTest.java b/user/test/com/google/gwt/emultest/java/lang/reflect/ArrayTest.java
index 420248c..9a8472f 100644
--- a/user/test/com/google/gwt/emultest/java/lang/reflect/ArrayTest.java
+++ b/user/test/com/google/gwt/emultest/java/lang/reflect/ArrayTest.java
@@ -143,6 +143,12 @@
     }
 
     assertEquals(1.0d, Array.getDouble(new double[] {1.0d}, 0));
+    assertEquals(1.0d, Array.getDouble(new float[] {1.0f}, 0));
+    assertEquals(1.0d, Array.getDouble(new byte[] {1}, 0));
+    assertEquals(1.0d, Array.getDouble(new char[] {1}, 0));
+    assertEquals(1.0d, Array.getDouble(new int[] {1}, 0));
+    assertEquals(1.0d, Array.getDouble(new long[] {1}, 0));
+    assertEquals(1.0d, Array.getDouble(new short[] {1}, 0));
   }
 
   public void testGetFloat() {
@@ -165,6 +171,11 @@
     }
 
     assertEquals(1.0f, Array.getFloat(new float[] {1.0f}, 0));
+    assertEquals(1.0f, Array.getFloat(new byte[] {1}, 0));
+    assertEquals(1.0f, Array.getFloat(new char[] {1}, 0));
+    assertEquals(1.0f, Array.getFloat(new int[] {1}, 0));
+    assertEquals(1.0f, Array.getFloat(new long[] {1}, 0));
+    assertEquals(1.0f, Array.getFloat(new short[] {1}, 0));
   }
 
   public void testGetInt() {
@@ -187,6 +198,9 @@
     }
 
     assertEquals(1, Array.getInt(new int[] {1}, 0));
+    assertEquals(1, Array.getInt(new byte[] {1}, 0));
+    assertEquals(1, Array.getInt(new char[] {1}, 0));
+    assertEquals(1, Array.getInt(new short[] {1}, 0));
   }
 
   public void testGetLength() {
@@ -222,6 +236,10 @@
     }
 
     assertEquals(1L, Array.getLong(new long[] {1L}, 0));
+    assertEquals(1L, Array.getLong(new byte[] {1}, 0));
+    assertEquals(1L, Array.getLong(new char[] {1}, 0));
+    assertEquals(1L, Array.getLong(new int[] {1}, 0));
+    assertEquals(1L, Array.getLong(new short[] {1}, 0));
   }
 
   public void testGetShort() {
@@ -244,6 +262,7 @@
     }
 
     assertEquals((short) 1, Array.getShort(new short[] {(short) 1}, 0));
+    assertEquals((short) 1, Array.getShort(new short[] {1}, 0));
   }
 
   public void testSet() {
@@ -294,6 +313,39 @@
     short[] shortArray = new short[1];
     Array.set(shortArray, 0, (short) 1);
     assertEquals((short) 1, shortArray[0]);
+
+    // test widening
+    long[] otherLongArray = new long[10];
+    Array.set(otherLongArray, 0, (byte) 2);
+    assertEquals(2L, otherLongArray[0]);
+
+    Array.set(otherLongArray, 1, (short) 3);
+    assertEquals(3L, otherLongArray[1]);
+
+    Array.set(otherLongArray, 2, (char) 4);
+    assertEquals(4L, otherLongArray[2]);
+
+    Array.set(otherLongArray, 3, 5);
+    assertEquals(5L, otherLongArray[3]);
+
+    double[] otherDoubleArray = new double[10];
+    Array.set(otherDoubleArray, 0, (byte) 2);
+    assertEquals(2d, otherDoubleArray[0], 0.00001);
+
+    Array.set(otherDoubleArray, 1, (short) 3);
+    assertEquals(3d, otherDoubleArray[1], 0.00001);
+
+    Array.set(otherDoubleArray, 2, (char) 4);
+    assertEquals(4d, otherDoubleArray[2], 0.00001);
+
+    Array.set(otherDoubleArray, 3, 5);
+    assertEquals(5d, otherDoubleArray[3], 0.00001);
+
+    Array.set(otherDoubleArray, 4, (float) 6);
+    assertEquals(6d, otherDoubleArray[4], 0.00001);
+
+    Array.set(otherDoubleArray, 5, (double) 7);
+    assertEquals(7d, otherDoubleArray[5], 0.00001);
   }
 
   public void testSetBoolean() {
@@ -328,10 +380,29 @@
     } catch (RuntimeException expected) {
     }
 
-    byte[] array = new byte[1];
+    byte[] bArray = new byte[1];
+    Array.setByte(bArray, 0, (byte) 1);
+    assertEquals((byte) 1, bArray[0]);
 
-    Array.setByte(array, 0, (byte) 1);
-    assertEquals((byte) 1, array[0]);
+    double[] dArray = new double[1];
+    Array.setByte(dArray, 0, (byte) 1);
+    assertEquals((byte) 1, (byte) dArray[0]);
+
+    float[] fArray = new float[1];
+    Array.setByte(fArray, 0, (byte) 1);
+    assertEquals((byte) 1, (byte) fArray[0]);
+
+    int[] iArray = new int[1];
+    Array.setByte(iArray, 0, (byte) 1);
+    assertEquals((byte) 1, (byte) iArray[0]);
+
+    long[] lArray = new long[1];
+    Array.setByte(lArray, 0, (byte) 1);
+    assertEquals((byte) 1, (byte) lArray[0]);
+
+    short[] sArray = new short[1];
+    Array.setByte(sArray, 0, (byte) 1);
+    assertEquals((byte) 1, (byte) sArray[0]);
   }
 
   public void testSetChar() {
@@ -351,6 +422,22 @@
 
     Array.setChar(array, 0, 'a');
     assertEquals('a', array[0]);
+
+    double[] dArray = new double[1];
+    Array.setChar(dArray, 0, (char) 1);
+    assertEquals((byte) 1, (byte) dArray[0]);
+
+    float[] fArray = new float[1];
+    Array.setChar(fArray, 0, (char) 1);
+    assertEquals((byte) 1, (byte) fArray[0]);
+
+    int[] iArray = new int[1];
+    Array.setChar(iArray, 0, (char) 1);
+    assertEquals((byte) 1, (byte) iArray[0]);
+
+    long[] lArray = new long[1];
+    Array.setChar(lArray, 0, (char) 1);
+    assertEquals((byte) 1, (byte) lArray[0]);
   }
 
   public void testSetDouble() {
@@ -389,6 +476,10 @@
 
     Array.setFloat(array, 0, 1.0f);
     assertEquals(1.0f, array[0]);
+
+    double[] dArray = new double[1];
+    Array.setFloat(dArray, 0, 1);
+    assertEquals((float) 1, (float) dArray[0]);
   }
 
   public void testSetInt() {
@@ -408,6 +499,18 @@
 
     Array.setInt(array, 0, 1);
     assertEquals(1, array[0]);
+
+    double[] dArray = new double[1];
+    Array.setInt(dArray, 0, 1);
+    assertEquals(1, (int) dArray[0]);
+
+    float[] fArray = new float[1];
+    Array.setInt(fArray, 0, 1);
+    assertEquals(1, (int) fArray[0]);
+
+    long[] lArray = new long[1];
+    Array.setInt(lArray, 0, 1);
+    assertEquals(1, (int) lArray[0]);
   }
 
   public void testSetLong() {
@@ -427,6 +530,14 @@
 
     Array.setLong(array, 0, 1L);
     assertEquals(1L, array[0]);
+
+    double[] dArray = new double[1];
+    Array.setLong(dArray, 0, 1);
+    assertEquals(1L, (long) dArray[0]);
+
+    float[] fArray = new float[1];
+    Array.setLong(fArray, 0, 1);
+    assertEquals(1L, (long) fArray[0]);
   }
 
   public void testSetShort() {
@@ -446,5 +557,21 @@
 
     Array.setShort(array, 0, (short) 1);
     assertEquals((short) 1, array[0]);
+
+    int[] iArray = new int[1];
+    Array.setShort(iArray, 0, (short) 1);
+    assertEquals((short) 1, (short) iArray[0]);
+
+    double[] dArray = new double[1];
+    Array.setShort(dArray, 0, (short) 1);
+    assertEquals((short) 1, (short) dArray[0]);
+
+    float[] fArray = new float[1];
+    Array.setShort(fArray, 0, (short) 1);
+    assertEquals((short) 1, (short) fArray[0]);
+
+    long[] lArray = new long[1];
+    Array.setShort(lArray, 0, (short) 1);
+    assertEquals((short) 1, (short) lArray[0]);
   }
 }