/*
 * Copyright (C) 2011 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.
 */

package art;

import java.lang.reflect.Method;
import java.util.Set;
import java.util.HashSet;

public class Test989 {
  static boolean PRINT_STACK_TRACE = false;
  static Set<Method> testMethods = new HashSet<>();

  static MethodTracer currentTracer = new MethodTracer() {
    public void methodEntry(Object o) { return; }
    public void methodExited(Object o, boolean e, Object r) { return; }
  };

  private static boolean DISABLE_TRACING = false;

  static {
    try {
      testMethods.add(Test989.class.getDeclaredMethod("doNothing"));
      testMethods.add(Test989.class.getDeclaredMethod("doNothingNative"));
      testMethods.add(Test989.class.getDeclaredMethod("throwA"));
      testMethods.add(Test989.class.getDeclaredMethod("throwANative"));
      testMethods.add(Test989.class.getDeclaredMethod("returnFloat"));
      testMethods.add(Test989.class.getDeclaredMethod("returnFloatNative"));
      testMethods.add(Test989.class.getDeclaredMethod("returnDouble"));
      testMethods.add(Test989.class.getDeclaredMethod("returnDoubleNative"));
      testMethods.add(Test989.class.getDeclaredMethod("returnValue"));
      testMethods.add(Test989.class.getDeclaredMethod("returnValueNative"));
      testMethods.add(Test989.class.getDeclaredMethod("acceptValue", Object.class));
      testMethods.add(Test989.class.getDeclaredMethod("acceptValueNative", Object.class));
      testMethods.add(Test989.class.getDeclaredMethod("tryCatchExit"));
    } catch (Exception e) {
      throw new Error("Bad static!", e);
    }
  }

  // Disables tracing only on RI. Used to work around an annoying piece of behavior where in the
  // RI throwing an exception in an exit hook causes the exit hook to be re-executed. This leads
  // to an infinite loop on the RI.
  private static void disableTraceForRI() {
    if (!System.getProperty("java.vm.name").equals("Dalvik")) {
      Trace.disableTracing(Thread.currentThread());
    }
  }

  private static String getInfo(Object m, boolean exception, Object result) {
    String out = m.toString() + " returned ";
    if (exception) {
      out += "<exception>";
    } else {
      out += result;
    }
    return out;
  }

  public static interface MethodTracer {
    public void methodEntry(Object m);
    public void methodExited(Object m, boolean exception, Object result);
    public default Class<?> entryException() { return null; }
    public default Class<?> exitException() { return null; }
  }

  public static class NormalTracer implements MethodTracer {
    public void methodEntry(Object m) {
      if (testMethods.contains(m)) {
        System.out.println("Normal: Entering " + m);
      }
    }
    public void methodExited(Object m, boolean exception, Object result) {
      if (testMethods.contains(m)) {
        System.out.println("Normal: Leaving " + getInfo(m, exception, result));
      }
    }
  }

  public static class ThrowEnterTracer implements MethodTracer {
    public void methodEntry(Object m) {
      if (testMethods.contains(m)) {
        System.out.println("ThrowEnter: Entering " + m);
        throw new ErrorB("Throwing error while entering " + m);
      }
    }
    public void methodExited(Object m, boolean exception, Object result) {
      if (testMethods.contains(m)) {
        System.out.println("ThrowEnter: Leaving " + getInfo(m, exception, result));
      }
    }
    public Class<?> entryException() { return ErrorB.class; }
  }

  public static class ThrowExitTracer implements MethodTracer {
    public void methodEntry(Object m) {
      if (testMethods.contains(m)) {
        System.out.println("ThrowExit: Entering " + m);
      }
    }
    public void methodExited(Object m, boolean exception, Object result) {
      if (testMethods.contains(m)) {
        // The RI goes into an infinite loop if we throw exceptions in an ExitHook. See
        // disableTraceForRI for explanation.
        disableTraceForRI();
        System.out.println("ThrowExit: Leaving " + getInfo(m, exception, result));
        throw new ErrorB("Throwing error while exit " + getInfo(m, exception, result));
      }
    }
    public Class<?> exitException() { return ErrorB.class; }
  }

  public static class ThrowBothTracer implements MethodTracer {
    public void methodEntry(Object m) {
      if (testMethods.contains(m)) {
        System.out.println("ThrowBoth: Entering " + m);
        throw new ErrorB("Throwing error while entering " + m);
      }
    }
    public void methodExited(Object m, boolean exception, Object result) {
      if (testMethods.contains(m)) {
        // The RI goes into an infinite loop if we throw exceptions in an ExitHook. See
        // disableTraceForRI for explanation.
        disableTraceForRI();
        System.out.println("ThrowBoth: Leaving " + getInfo(m, exception, result));
        throw new ErrorC("Throwing error while exit " + getInfo(m, exception, result));
      }
    }
    public Class<?> entryException() { return ErrorB.class; }
    public Class<?> exitException() { return ErrorC.class; }
  }

  public static class ForceGCTracer implements MethodTracer {
    public void methodEntry(Object m) {
      if (System.getProperty("java.vm.name").equals("Dalvik") &&
          testMethods.contains(m)) {
        Runtime.getRuntime().gc();
      }
    }
    public void methodExited(Object m, boolean exception, Object result) {
      if (System.getProperty("java.vm.name").equals("Dalvik") &&
          testMethods.contains(m)) {
        Runtime.getRuntime().gc();
      }
    }
  }

  private static void maybeDisableTracing() throws Exception {
    if (DISABLE_TRACING) {
      Trace.disableTracing(Thread.currentThread());
    }
  }

  public static void baseNotifyMethodEntry(Object o) {
    currentTracer.methodEntry(o);
  }
  public static void baseNotifyMethodExit(Object o, boolean exception, Object res) {
    currentTracer.methodExited(o, exception, res);
  }

  private static void setupTracing() throws Exception {
    Trace.enableMethodTracing(
        Test989.class,
        Test989.class.getDeclaredMethod("baseNotifyMethodEntry", Object.class),
        Test989.class.getDeclaredMethod(
            "baseNotifyMethodExit", Object.class, Boolean.TYPE, Object.class),
        Thread.currentThread());
  }
  private static void setEntry(MethodTracer type) throws Exception {
    if (DISABLE_TRACING || !System.getProperty("java.vm.name").equals("Dalvik")) {
      Trace.disableTracing(Thread.currentThread());
      setupTracing();
    }
    currentTracer = type;
  }

  private static String testDescription(MethodTracer type, Runnable test) {
    return "test[" + type.getClass() + ", " + test.getClass() + "]";
  }

  private static Class<?> getExpectedError(MethodTracer t, MyRunnable r) {
    if (t.exitException() != null) {
      return t.exitException();
    } else if (t.entryException() != null) {
      return t.entryException();
    } else {
      return r.expectedThrow();
    }
  }

  private static void doTest(MethodTracer type, MyRunnable test) throws Exception {
    Class<?> expected = getExpectedError(type, test);

    setEntry(type);
    try {
      test.run();
      // Disabling method tracing just makes this test somewhat faster.
      maybeDisableTracing();
      if (expected == null) {
        System.out.println(
            "Received no exception as expected for " + testDescription(type, test) + ".");
        return;
      }
    } catch (Error t) {
      // Disabling method tracing just makes this test somewhat faster.
      maybeDisableTracing();
      if (expected == null) {
        throw new Error("Unexpected error occured: " + t + " for " + testDescription(type, test), t);
      } else if (!expected.isInstance(t)) {
        throw new Error("Expected error of type " + expected + " not " + t +
            " for " + testDescription(type, test), t);
      } else {
        System.out.println(
            "Received expected error for " + testDescription(type, test) + " - " + t);
        if (PRINT_STACK_TRACE) {
          t.printStackTrace();
        }
        return;
      }
    }
    System.out.println("Expected an error of type " + expected + " but got no exception for "
        + testDescription(type, test));
    // throw new Error("Expected an error of type " + expected + " but got no exception for "
    //     + testDescription(type, test));
  }

  public static interface MyRunnable extends Runnable {
    public default Class<?> expectedThrow() {
      return null;
    }
  }

  public static void run() throws Exception {
    MyRunnable[] testCases = new MyRunnable[] {
      new doNothingClass(),
      new doNothingNativeClass(),
      new throwAClass(),
      new throwANativeClass(),
      new returnValueClass(),
      new returnValueNativeClass(),
      new acceptValueClass(),
      new acceptValueNativeClass(),
      new tryCatchExitClass(),
      new returnFloatClass(),
      new returnFloatNativeClass(),
      new returnDoubleClass(),
      new returnDoubleNativeClass(),
    };
    MethodTracer[] tracers = new MethodTracer[] {
      new NormalTracer(),
      new ThrowEnterTracer(),
      new ThrowExitTracer(),
      new ThrowBothTracer(),
      new ForceGCTracer(),
    };

    setupTracing();
    for (MethodTracer t : tracers) {
      for (MyRunnable r : testCases) {
        doTest(t, r);
      }
    }

    maybeDisableTracing();
    System.out.println("Finished!");
    Trace.disableTracing(Thread.currentThread());
  }

  private static final class throwAClass implements MyRunnable {
    public void run() {
      throwA();
    }
    @Override
    public Class<?> expectedThrow() {
      return ErrorA.class;
    }
  }

  private static final class throwANativeClass implements MyRunnable {
    public void run() {
      throwANative();
    }
    @Override
    public Class<?> expectedThrow() {
      return ErrorA.class;
    }
  }

  private static final class tryCatchExitClass implements MyRunnable {
    public void run() {
      tryCatchExit();
    }
  }

  private static final class doNothingClass implements MyRunnable {
    public void run() {
      doNothing();
    }
  }

  private static final class doNothingNativeClass implements MyRunnable {
    public void run() {
      doNothingNative();
    }
  }

  private static final class acceptValueClass implements MyRunnable {
    public void run() {
      acceptValue(mkTestObject());
    }
  }

  private static final class acceptValueNativeClass implements MyRunnable {
    public void run() {
      acceptValueNative(mkTestObject());
    }
  }

  private static final class returnValueClass implements MyRunnable {
    public void run() {
      Object o = returnValue();
      System.out.println("returnValue returned: " + o);
    }
  }

  private static final class returnValueNativeClass implements MyRunnable {
    public void run() {
      Object o = returnValueNative();
      System.out.println("returnValueNative returned: " + o);
    }
  }

  private static final class returnFloatClass implements MyRunnable {
    public void run() {
      float d = returnFloat();
      System.out.println("returnFloat returned: " + d);
    }
  }

  private static final class returnFloatNativeClass implements MyRunnable {
    public void run() {
      float d = returnFloatNative();
      System.out.println("returnFloatNative returned: " + d);
    }
  }

  private static final class returnDoubleClass implements MyRunnable {
    public void run() {
      double d = returnDouble();
      System.out.println("returnDouble returned: " + d);
    }
  }

  private static final class returnDoubleNativeClass implements MyRunnable {
    public void run() {
      double d = returnDoubleNative();
      System.out.println("returnDoubleNative returned: " + d);
    }
  }

  private static class ErrorA extends Error {
    private static final long serialVersionUID = 0;
    public ErrorA(String s) { super(s); }
  }

  private static class ErrorB extends Error {
    private static final long serialVersionUID = 1;
    public ErrorB(String s) { super(s); }
  }

  private static class ErrorC extends Error {
    private static final long serialVersionUID = 2;
    public ErrorC(String s) { super(s); }
  }

  // Does nothing.
  public static void doNothing() { }

  public static void tryCatchExit() {
    try {
      Object o = mkTestObject();
      return;
    } catch (ErrorB b) {
      System.out.println("ERROR: Caught " + b);
      b.printStackTrace();
    } catch (ErrorC c) {
      System.out.println("ERROR: Caught " + c);
      c.printStackTrace();
    }
  }

  public static float returnFloat() {
    return doGetFloat();
  }

  public static double returnDouble() {
    return doGetDouble();
  }

  // Throws an ErrorA.
  public static void throwA() {
    doThrowA();
  }

  public static void doThrowA() {
    throw new ErrorA("Throwing Error A");
  }

  static final class TestObject {
    private int idx;
    public TestObject(int v) {
      this.idx = v;
    }
    @Override
    public String toString() {
      return "TestObject(" + idx + ")";
    }
  }

  static int counter = 0;
  public static Object mkTestObject() {
    return new TestObject(counter++);
  }

  public static void printObject(Object o) {
    System.out.println("Recieved " + o);
  }

  // Returns a newly allocated value.
  public static Object returnValue() {
    return mkTestObject();
  }

  public static void acceptValue(Object o) {
    printObject(o);
  }

  public static float doGetFloat() {
    return 1.618f;
  }

  public static double doGetDouble() {
    return 3.14159628;
  }

  // Calls mkTestObject from native code and returns it.
  public static native Object returnValueNative();
  // Calls printObject from native code.
  public static native void acceptValueNative(Object t);
  public static native void doNothingNative();
  public static native void throwANative();
  public static native float returnFloatNative();
  public static native double returnDoubleNative();
}
