/*
 * Copyright (C) 2013 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.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Field;
import java.lang.reflect.Proxy;
import java.util.regex.Pattern;

import dalvik.annotation.optimization.CriticalNative;
import dalvik.annotation.optimization.FastNative;

public class Main {
    public static void main(String[] args) {
        System.loadLibrary(args[0]);

        if (!isSlowDebug()) {
          throw new RuntimeException("Slow-debug flags unexpectedly off.");
        }

        testFieldSubclass();
        testFindClassOnAttachedNativeThread();
        testFindFieldOnAttachedNativeThread();
        testReflectFieldGetFromAttachedNativeThreadNative();
        testCallStaticVoidMethodOnSubClass();
        testGetMirandaMethod();
        testZeroLengthByteBuffers();
        testByteMethod();
        testShortMethod();
        testBooleanMethod();
        testCharMethod();
        testIsAssignableFromOnPrimitiveTypes();
        testShallowGetCallingClassLoader();
        testShallowGetStackClass2();
        testCallNonvirtual();
        testNewStringObject();
        testRemoveLocalObject();
        testProxyGetMethodID();
        testJniCriticalSectionAndGc();
        testCallDefaultMethods();
        String lambda = "λ";
        testInvokeLambdaMethod(() -> { System.out.println("hi-lambda: " + lambda); });
        String def = "δ";
        testInvokeLambdaDefaultMethod(() -> { System.out.println("hi-default " + def + lambda); });

        registerNativesJniTest();
        testFastNativeMethods();
        testCriticalNativeMethods();

        testClinitMethodLookup();

        testDoubleLoad(args[0]);
        testUTFRegion("\0\0\0");
    }

    static class ABC { public static int XYZ = 12; }
    static class DEF extends ABC {}
    public static void testFieldSubclass() {
      try {
        System.out.println("ABC.XYZ = " + ABC.XYZ + ", GetStaticIntField(DEF.class, 'XYZ') = " +
            getFieldSubclass(ABC.class.getDeclaredField("XYZ"), DEF.class));
      } catch (Exception e) {
        throw new RuntimeException("Failed to test get static field on a subclass", e);
      }
    }

    public static native void testUTFRegion(String null_str);

    public static native int getFieldSubclass(Field f, Class sub);

    private static native boolean registerNativesJniTest();

    private static native void testCallDefaultMethods();

    private static native void testFindClassOnAttachedNativeThread();

    private static boolean testFindFieldOnAttachedNativeThreadField;

    private static native void testReflectFieldGetFromAttachedNativeThreadNative();

    public static boolean testReflectFieldGetFromAttachedNativeThreadField;

    private static void testFindFieldOnAttachedNativeThread() {
      testFindFieldOnAttachedNativeThreadNative();
      if (!testFindFieldOnAttachedNativeThreadField) {
            throw new AssertionError();
        }
    }

    private static native void testFindFieldOnAttachedNativeThreadNative();

    private static void testCallStaticVoidMethodOnSubClass() {
        testCallStaticVoidMethodOnSubClassNative();
        if (!testCallStaticVoidMethodOnSubClass_SuperClass.executed) {
            throw new AssertionError();
        }
    }

    private static native void testCallStaticVoidMethodOnSubClassNative();

    private static class testCallStaticVoidMethodOnSubClass_SuperClass {
        private static boolean executed = false;
        private static void execute() {
            executed = true;
        }
    }

    private static class testCallStaticVoidMethodOnSubClass_SubClass
        extends testCallStaticVoidMethodOnSubClass_SuperClass {
    }

    private static native Method testGetMirandaMethodNative();

    private static void testGetMirandaMethod() {
        Method m = testGetMirandaMethodNative();
        if (m.getDeclaringClass() != testGetMirandaMethod_MirandaInterface.class) {
            throw new AssertionError();
        }
    }

    private static native void testZeroLengthByteBuffers();

    private static abstract class testGetMirandaMethod_MirandaAbstract implements testGetMirandaMethod_MirandaInterface {
        public boolean inAbstract() {
            return true;
        }
    }

    private static interface testGetMirandaMethod_MirandaInterface {
        public boolean inInterface();
    }

    // Test sign-extension for values < 32b

    static native byte byteMethod(byte b1, byte b2, byte b3, byte b4, byte b5, byte b6, byte b7,
        byte b8, byte b9, byte b10);

    private static void testByteMethod() {
      byte returns[] = { 0, 1, 2, 127, -1, -2, -128 };
      for (int i = 0; i < returns.length; i++) {
        byte result = byteMethod((byte)i, (byte)2, (byte)(-3), (byte)4, (byte)(-5), (byte)6,
            (byte)(-7), (byte)8, (byte)(-9), (byte)10);
        if (returns[i] != result) {
          System.out.println("Run " + i + " with " + returns[i] + " vs " + result);
          throw new AssertionError();
        }
      }
    }

    private static native void removeLocalObject(Object o);

    private static void testRemoveLocalObject() {
        removeLocalObject(new Object());
    }

    private static native short shortMethod(short s1, short s2, short s3, short s4, short s5, short s6, short s7,
        short s8, short s9, short s10);

    private static void testShortMethod() {
      short returns[] = { 0, 1, 2, 127, 32767, -1, -2, -128, -32768 };
      for (int i = 0; i < returns.length; i++) {
        short result = shortMethod((short)i, (short)2, (short)(-3), (short)4, (short)(-5), (short)6,
            (short)(-7), (short)8, (short)(-9), (short)10);
        if (returns[i] != result) {
          System.out.println("Run " + i + " with " + returns[i] + " vs " + result);
          throw new AssertionError();
        }
      }
    }

    // Test zero-extension for values < 32b

    private static native boolean booleanMethod(boolean b1, boolean b2, boolean b3, boolean b4, boolean b5, boolean b6, boolean b7,
        boolean b8, boolean b9, boolean b10);

    private static void testBooleanMethod() {
      if (booleanMethod(false, true, false, true, false, true, false, true, false, true)) {
        throw new AssertionError();
      }

      if (!booleanMethod(true, true, false, true, false, true, false, true, false, true)) {
        throw new AssertionError();
      }
    }

    private static native char charMethod(char c1, char c2, char c3, char c4, char c5, char c6, char c7,
        char c8, char c9, char c10);

    private static void testCharMethod() {
      char returns[] = { (char)0, (char)1, (char)2, (char)127, (char)255, (char)256, (char)15000,
          (char)34000 };
      for (int i = 0; i < returns.length; i++) {
        char result = charMethod((char)i, 'a', 'b', 'c', '0', '1', '2', (char)1234, (char)2345,
            (char)3456);
        if (returns[i] != result) {
          System.out.println("Run " + i + " with " + (int)returns[i] + " vs " + (int)result);
          throw new AssertionError();
        }
      }
    }

    // http://b/16531674
    private static void testIsAssignableFromOnPrimitiveTypes() {
      if (!nativeIsAssignableFrom(int.class, Integer.TYPE)) {
        System.out.println("IsAssignableFrom(int.class, Integer.TYPE) returned false, expected true");
        throw new AssertionError();
      }

      if (!nativeIsAssignableFrom(Integer.TYPE, int.class)) {
        System.out.println("IsAssignableFrom(Integer.TYPE, int.class) returned false, expected true");
        throw new AssertionError();
      }
    }

    private static native boolean nativeIsAssignableFrom(Class<?> from, Class<?> to);

    private static void testShallowGetCallingClassLoader() {
        nativeTestShallowGetCallingClassLoader();
    }

    private native static void nativeTestShallowGetCallingClassLoader();

    private static void testShallowGetStackClass2() {
        nativeTestShallowGetStackClass2();
    }

    private static native void nativeTestShallowGetStackClass2();

    private static native void testCallNonvirtual();

    private static native void testNewStringObject();

    private interface SimpleInterface {
        void a();
    }

    private static class MinimalInvocationHandler implements InvocationHandler {
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            return null;
        }
    }

    private static void testProxyGetMethodID() {
        InvocationHandler handler = new MinimalInvocationHandler();
        SimpleInterface proxy =
                (SimpleInterface) Proxy.newProxyInstance(SimpleInterface.class.getClassLoader(),
                        new Class<?>[] {SimpleInterface.class}, handler);
        if (testGetMethodID(SimpleInterface.class) == 0) {
            throw new AssertionError();
        }
        if (testGetMethodID(proxy.getClass()) == 0) {
            throw new AssertionError();
        }
    }

    private static native long testGetMethodID(Class<?> c);

    // Exercise GC and JNI critical sections in parallel.
    private static void testJniCriticalSectionAndGc() {
        Thread runGcThread = new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 10; ++i) {
                    Runtime.getRuntime().gc();
                }
            }
        });
        Thread jniCriticalThread = new Thread(new Runnable() {
            @Override
            public void run() {
                final int arraySize = 32;
                byte[] array0 = new byte[arraySize];
                byte[] array1 = new byte[arraySize];
                enterJniCriticalSection(arraySize, array0, array1);
            }
        });
        jniCriticalThread.start();
        runGcThread.start();
        try {
            jniCriticalThread.join();
            runGcThread.join();
        } catch (InterruptedException ignored) {}
    }

    private static native void enterJniCriticalSection(int arraySize, byte[] array0, byte[] array);

    private static native void testInvokeLambdaMethod(LambdaInterface iface);

    private static native void testInvokeLambdaDefaultMethod(LambdaInterface iface);

    // Test invoking @FastNative methods works correctly.

    // Return sum of a+b+c.
    @FastNative
    static native int intFastNativeMethod(int a, int b, int c);

    private static void testFastNativeMethods() {
      int returns[] = { 0, 3, 6, 9, 12 };
      for (int i = 0; i < returns.length; i++) {
        int result = intFastNativeMethod(i, i, i);
        if (returns[i] != result) {
          System.out.println("FastNative Int Run " + i + " with " + returns[i] + " vs " + result);
          throw new AssertionError();
        }
      }
    }

    // Smoke test for @CriticalNative
    // TODO: Way more thorough tests since it involved quite a bit of changes.

    // Return sum of a+b+c.
    @CriticalNative
    static native int intCriticalNativeMethod(int a, int b, int c);

    private static void testCriticalNativeMethods() {
      int returns[] = { 3, 6, 9, 12, 15 };
      for (int i = 0; i < returns.length; i++) {
        int result = intCriticalNativeMethod(i, i+1, i+2);
        if (returns[i] != result) {
          System.out.println("CriticalNative Int Run " + i + " with " + returns[i] + " vs " + result);
          throw new AssertionError();
        }
      }
    }

    private static native boolean isSlowDebug();

    private static void testClinitMethodLookup() {
      // Expect this to print <NSME Exception>
      try {
        System.out.println("Clinit Lookup: ClassWithoutClinit: " + methodString(lookupClinit(ClassWithoutClinit.class)));
      } catch (NoSuchMethodError e) {
        System.out.println("Clinit Lookup: ClassWithoutClinit: <NSME Exception>");
      }
      // Expect this to print <clinit>
      try {
        System.out.println("Clinit Lookup: ClassWithClinit: " + methodString(lookupClinit(ClassWithClinit.class)));
      } catch (NoSuchMethodError e) {
        System.out.println("Clinit Lookup: ClassWithClinit: <NSME Exception>");
      }
   }

    private static String methodString(java.lang.reflect.Executable method) {
      if (method == null) {
        return "<<null>>";
      } else {
        return method.toString() + "(Class: " + method.getClass().toString() + ")";
      }
    }
    private static native java.lang.reflect.Executable lookupClinit(Class kls);

    private static class ClassWithoutClinit {
    }
    private static class ClassWithClinit {
      static {}
    }

  private static void testDoubleLoad(String library) {
    // Test that nothing observably happens on loading "library" again.
    System.loadLibrary(library);

    // Now load code in a separate classloader and try to let it load.
    ClassLoader loader = createClassLoader();
    try {
      Class<?> aClass = loader.loadClass("A");
      Method runMethod = aClass.getDeclaredMethod("run", String.class);
      runMethod.invoke(null, library);
    } catch (InvocationTargetException ite) {
      if (ite.getCause() instanceof UnsatisfiedLinkError) {
        if (!(loader instanceof java.net.URLClassLoader)) {
          String msg = ite.getCause().getMessage();
          String pattern = "^Shared library .*libarttest.* already opened by ClassLoader.*" +
                           "004-JniTest.jar.*; can't open in ClassLoader.*004-JniTest-ex.jar.*";
          if (!Pattern.matches(pattern, msg)) {
            throw new RuntimeException("Could not find pattern in message", ite.getCause());
          }
        }
        System.out.println("Got UnsatisfiedLinkError for duplicate loadLibrary");
      } else {
        throw new RuntimeException(ite);
      }
    } catch (Throwable t) {
      // Anything else just let die.
      throw new RuntimeException(t);
    }
  }

  private static ClassLoader createClassLoader() {
    String location = System.getenv("DEX_LOCATION");
    try {
      Class<?> class_loader_class = Class.forName("dalvik.system.PathClassLoader");
      Constructor<?> ctor = class_loader_class.getConstructor(String.class, ClassLoader.class);

      return (ClassLoader)ctor.newInstance(location + "/004-JniTest-ex.jar",
                                           Main.class.getClassLoader());
    } catch (ClassNotFoundException e) {
      // Running on RI. Use URLClassLoader.
      try {
        return new java.net.URLClassLoader(
            new java.net.URL[] { new java.net.URL("file://" + location + "/classes-ex/") });
      } catch (Throwable t) {
        throw new RuntimeException(t);
      }
    } catch (Throwable t) {
      throw new RuntimeException(t);
    }
  }
}

@FunctionalInterface
interface LambdaInterface {
  public void sayHi();
  public default void sayHiTwice() {
    sayHi();
    sayHi();
  }
}

class JniCallNonvirtualTest {
    public boolean nonstaticMethodSuperCalled = false;
    public boolean nonstaticMethodSubCalled = false;

    private static native void testCallNonvirtual();

    public JniCallNonvirtualTest() {
        System.out.println("Super.<init>");
    }

    public static void staticMethod() {
        System.out.println("Super.staticMethod");
    }

    public void nonstaticMethod() {
        System.out.println("Super.nonstaticMethod");
        nonstaticMethodSuperCalled = true;
    }
}

class JniCallNonvirtualTestSubclass extends JniCallNonvirtualTest {

    public JniCallNonvirtualTestSubclass() {
        System.out.println("Subclass.<init>");
    }

    public static void staticMethod() {
        System.out.println("Subclass.staticMethod");
    }

    public void nonstaticMethod() {
        System.out.println("Subclass.nonstaticMethod");
        nonstaticMethodSubCalled = true;
    }
}
