/*
 * Copyright (C) 2012 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class Main {
  public static void main(String[] args) throws Exception {
    arrayAccess();
    arrayStore();
    classCast();
    classNotFound();
    negativeArraySize();
    nullPointers();
    reflection();
    stringIndex();
  }

  private static void assertEquals(String expected, String actual) {
    if (expected == null && actual == null) {
      return;
    }
    if (expected != null && expected.equals(actual)) {
      return;
    }
    throw new AssertionError("not equal\n" +
                                 "expected: " + expected + "\n" +
                                 "actual:   " + actual);
  }

  private static void fail() {
    throw new AssertionError();
  }

  private static void arrayAccess() throws Exception {
    byte[] bs = new byte[1];
    double[] ds = new double[1];
    Object[] os = new Object[1];

    // aput
    try {
      bs[2] = 0;
      fail();
    } catch (ArrayIndexOutOfBoundsException ex) {
      assertEquals("length=1; index=2", ex.getMessage());
    }

    // aget
    try {
      byte b = bs[2];
      fail();
    } catch (ArrayIndexOutOfBoundsException ex) {
      assertEquals("length=1; index=2", ex.getMessage());
    }

    // aput-wide
    try {
      ds[2] = 0.0;
      fail();
    } catch (ArrayIndexOutOfBoundsException ex) {
      assertEquals("length=1; index=2", ex.getMessage());
    }

    // aget-wide
    try {
      double d = ds[2];
      fail();
    } catch (ArrayIndexOutOfBoundsException ex) {
      assertEquals("length=1; index=2", ex.getMessage());
    }

    // aput-object
    try {
      os[2] = null;
      fail();
    } catch (ArrayIndexOutOfBoundsException ex) {
      assertEquals("length=1; index=2", ex.getMessage());
    }

    // aget-object
    try {
      Object o = os[2];
      fail();
    } catch (ArrayIndexOutOfBoundsException ex) {
      assertEquals("length=1; index=2", ex.getMessage());
    }
  }

  private static void arrayStore() throws Exception {
    try {
      Object[] array = new String[10];
      Object o = new Exception();
      array[0] = o;
      fail();
    } catch (ArrayStoreException ex) {
      assertEquals("java.lang.Exception cannot be stored in an array of type java.lang.String[]",
                   ex.getMessage());
    }

    try {
      Object[] array = new C[10][];
      Object o = new Integer(5);
      array[0] = o;
      fail();
    } catch (ArrayStoreException ex) {
      assertEquals("java.lang.Integer cannot be stored in an array of type Main$C[][]",
                   ex.getMessage());
    }

    try {
      Object[] array = new Float[10][];
      Object o = new C[4];
      array[0] = o;
      fail();
    } catch (ArrayStoreException ex) {
      assertEquals("Main$C[] cannot be stored in an array of type java.lang.Float[][]",
                   ex.getMessage());
    }

    try {
      String[] src = new String[] { null, null, null, null, "hello", "goodbye" };
      Integer[] dst = new Integer[10];
      System.arraycopy(src, 1, dst, 0, 5);
    } catch (ArrayStoreException ex) {
      assertEquals("source[4] of type java.lang.String cannot be stored in destination array of type java.lang.Integer[]",
                   ex.getMessage());
    }

    try {
      String[] src = new String[1];
      int[] dst = new int[1];
      System.arraycopy(src, 0, dst, 0, 1);
    } catch (ArrayStoreException ex) {
      assertEquals("Incompatible types: src=java.lang.String[], dst=int[]", ex.getMessage());
    }

    try {
      float[] src = new float[1];
      Runnable[] dst = new Runnable[1];
      System.arraycopy(src, 0, dst, 0, 1);
    } catch (ArrayStoreException ex) {
      assertEquals("Incompatible types: src=float[], dst=java.lang.Runnable[]", ex.getMessage());
    }

    try {
      boolean[] src = new boolean[1];
      double[][] dst = new double[1][];
      System.arraycopy(src, 0, dst, 0, 1);
    } catch (ArrayStoreException ex) {
      assertEquals("Incompatible types: src=boolean[], dst=double[][]", ex.getMessage());
    }

    try {
      String src = "hello";
      Object[] dst = new Object[1];
      System.arraycopy(src, 0, dst, 0, 1);
    } catch (ArrayStoreException ex) {
      assertEquals("source of type java.lang.String is not an array", ex.getMessage());
    }

    try {
      Object[] src = new Object[1];
      Integer dst = new Integer(5);
      System.arraycopy(src, 0, dst, 0, 1);
    } catch (ArrayStoreException ex) {
      assertEquals("destination of type java.lang.Integer is not an array", ex.getMessage());
    }

    // This test demonstrates that the exception message complains
    // about the source in cases where neither source nor
    // destination is an array.
    try {
      System.arraycopy(new C(), 0, "hello", 0, 1);
    } catch (ArrayStoreException ex) {
      assertEquals("source of type Main$C is not an array", ex.getMessage());
    }
  }

  private static void classCast() throws Exception {
    // Reference types.
    try {
      Object o = new Exception();
      String s = (String) o;
      fail();
    } catch (ClassCastException ex) {
      assertEquals("java.lang.Exception cannot be cast to java.lang.String", ex.getMessage());
    }

    // Arrays of reference types.
    try {
      Object o = (C) makeArray(String.class);
      fail();
    } catch (ClassCastException ex) {
      assertEquals("java.lang.String[] cannot be cast to Main$C", ex.getMessage());
    }

    // Arrays of primitives.
    try {
      Object o = (C) makeArray(float.class);
      fail();
    } catch (ClassCastException ex) {
      assertEquals("float[] cannot be cast to Main$C", ex.getMessage());
    }

    // Multi-dimensional arrays of primitives.
    try {
      Object o = (C) makeArray(char[].class);
      fail();
    } catch (ClassCastException ex) {
      assertEquals("char[][] cannot be cast to Main$C", ex.getMessage());
    }

    // Multi-dimensional arrays of references.
    try {
      Object o = (Object[][][]) makeInteger();
      fail();
    } catch (ClassCastException ex) {
      assertEquals("java.lang.Integer cannot be cast to java.lang.Object[][][]", ex.getMessage());
    }
  }

  static class C { }

  /**
   * Helper for testCastOperator and testCastOperatorWithArrays. It's important that the
   * return type is Object, since otherwise the compiler will just reject the code.
   */
  private static Object makeInteger() {
    return new Integer(5);
  }

  /**
   * Helper for testCastOperatorWithArrays. It's important that
   * the return type is Object.
   */
  private static Object makeArray(Class<?> c) {
    return Array.newInstance(c, 1);
  }

  private static void classNotFound() throws Exception {
    try {
      // There is no such thing as an array of void.
      Class.forName("[V");
      fail();
    } catch (ClassNotFoundException ex) {
      assertEquals("Invalid name: [V", ex.getMessage());
    }

    try {
      // This class name is valid, but doesn't exist.
      Class.forName("package.Class");
      fail();
    } catch (ClassNotFoundException ex) {
      assertEquals("package.Class", ex.getMessage());
    }

    try {
      // This array class name is valid, but the type doesn't exist.
      Class.forName("[[Lpackage.Class;");
      fail();
    } catch (ClassNotFoundException ex) {
      assertEquals("[[Lpackage.Class;", ex.getMessage());
    }
  }

  private static void negativeArraySize() throws Exception {
    try {
      int[] is = new int[-123];
      fail();
    } catch (NegativeArraySizeException ex) {
      assertEquals("-123", ex.getMessage());
    }
  }

  // Defeat the fact that null's are untyped for precise detail message creation with quickening.
  private static Object returnNullObject() {
    return null;
  }

  private static A returnNullA() {
    return null;
  }

  private static void nullPointers() throws Exception {
    // Invoke method.
    try {
      Object o = returnNullObject();
      o.hashCode();
      fail();
    } catch (NullPointerException ex) {
      assertEquals("Attempt to invoke virtual method 'int java.lang.Object.hashCode()' on a null object reference", ex.getMessage());
    }

    // Read field.
    try {
      A a = returnNullA();
      int i = a.i;
      fail();
    } catch (NullPointerException ex) {
      assertEquals(
          "Attempt to read from field 'int A.i' on a null object reference in method 'void Main.nullPointers()'",
          ex.getMessage());
    }

    // Write field.
    try {
      A a = returnNullA();
      a.i = 1;
      fail();
    } catch (NullPointerException ex) {
      assertEquals(
          "Attempt to write to field 'int A.i' on a null object reference in method 'void Main.nullPointers()'",
          ex.getMessage());
    }

    // Read array.
    try {
      int[] is = null;
      int i = is[0];
      fail();
    } catch (NullPointerException ex) {
      assertEquals("Attempt to read from null array", ex.getMessage());
    }

    // Write array.
    try {
      int[] is = null;
      is[0] = 1;
      fail();
    } catch (NullPointerException ex) {
      assertEquals("Attempt to write to null array", ex.getMessage());
    }

    // Array length.
    try {
      int[] is = null;
      int i = is.length;
      fail();
    } catch (NullPointerException ex) {
      assertEquals("Attempt to get length of null array", ex.getMessage());
    }
  }

  private static void reflection() throws Exception {
    // Can't assign Integer to a String field.
    try {
      Field field = A.class.getField("b");
      field.set(new A(), 5);
      fail();
    } catch (IllegalArgumentException expected) {
      assertEquals("field A.b has type java.lang.String, got java.lang.Integer",
          expected.getMessage());
    }

    // Can't unbox null to a primitive.
    try {
      Field field = A.class.getField("i");
      field.set(new A(), null);
      fail();
    } catch (IllegalArgumentException expected) {
      assertEquals("field A.i has type int, got null", expected.getMessage());
    }

    // Can't unbox String to a primitive.
    try {
      Field field = A.class.getField("i");
      field.set(new A(), "hello, world!");
      fail();
    } catch (IllegalArgumentException expected) {
      assertEquals("field A.i has type int, got java.lang.String", expected.getMessage());
    }

    // Can't pass an Integer as a String.
    try {
      Method m = A.class.getMethod("m", int.class, String.class);
      m.invoke(new A(), 2, 2);
      fail();
    } catch (IllegalArgumentException expected) {
      assertEquals("method A.m argument 2 has type java.lang.String, got java.lang.Integer",
          expected.getMessage());
    }

    // Can't pass null as an int.
    try {
      Method m = A.class.getMethod("m", int.class, String.class);
      m.invoke(new A(), null, "");
      fail();
    } catch (IllegalArgumentException expected) {
      assertEquals("method A.m argument 1 has type int, got null", expected.getMessage());
    }

    try {
      Method m = String.class.getMethod("charAt", int.class);
      m.invoke("hello"); // Wrong number of arguments.
      fail();
    } catch (IllegalArgumentException iae) {
      assertEquals("Wrong number of arguments; expected 1, got 0", iae.getMessage());
    }
    try {
      Method m = String.class.getMethod("charAt", int.class);
      m.invoke("hello", "world"); // Wrong type.
      fail();
    } catch (IllegalArgumentException iae) {
      assertEquals("method java.lang.String.charAt argument 1 has type int, got java.lang.String",
          iae.getMessage());
    }
    try {
      Method m = String.class.getMethod("charAt", int.class);
      m.invoke("hello", (Object) null); // Null for a primitive argument.
      fail();
    } catch (IllegalArgumentException iae) {
      assertEquals("method java.lang.String.charAt argument 1 has type int, got null",
          iae.getMessage());
    }
    try {
      Method m = String.class.getMethod("charAt", int.class);
      m.invoke(new Integer(5)); // Wrong type for 'this'.
      fail();
    } catch (IllegalArgumentException iae) {
      assertEquals("Expected receiver of type java.lang.String, but got java.lang.Integer",
          iae.getMessage());
    }
    try {
      Method m = String.class.getMethod("charAt", int.class);
      m.invoke(null); // Null for 'this'.
      fail();
    } catch (NullPointerException npe) {
      assertEquals("null receiver", npe.getMessage());
    }
  }

  private static void stringIndex() throws Exception {
    // charAt too small.
    try {
      "hello".charAt(-1);
      fail();
    } catch (StringIndexOutOfBoundsException ex) {
      assertEquals("length=5; index=-1", ex.getMessage());
    }

    // charAt too big.
    try {
      "hello".charAt(7);
      fail();
    } catch (StringIndexOutOfBoundsException ex) {
      assertEquals("length=5; index=7", ex.getMessage());
    }

    // substring too big.
    try {
      "hello there".substring(9,14);
      fail();
    } catch (StringIndexOutOfBoundsException ex) {
      assertEquals("begin 9, end 14, length 11", ex.getMessage());
    }
  }
}

class A {
  public String b;
  public int i;
  public void m(int i, String s) {}
}
