/*
 * Copyright (C) 2010 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.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

/*
 * Entry point and tests that are expected to succeed.
 */
public class Main {
    /**
     * Drives tests.
     */
    public static void main(String[] args) throws Exception {
        System.loadLibrary(args[0]);
        if (!hasOatFile() || runtimeIsSoftFail() || isInterpreted()) {
            // Some tests ensure that the verifier was able to guarantee balanced locking by
            // asserting that the test function is running as compiled code. But skip this now,
            // as this seems to be a non-compiled code test configuration.
            disableStackFrameAsserts();
        }

        ensureJitCompiled(Main.class, "recursiveSync");
        ensureJitCompiled(Main.class, "nestedMayThrow");
        ensureJitCompiled(Main.class, "constantLock");
        ensureJitCompiled(Main.class, "notExcessiveNesting");
        ensureJitCompiled(Main.class, "notNested");
        ensureJitCompiled(TwoPath.class, "twoPath");
        ensureJitCompiled(Class.forName("OK"), "runNoMonitors");
        ensureJitCompiled(Class.forName("OK"), "runStraightLine");
        ensureJitCompiled(Class.forName("OK"), "runBalancedJoin");
        ensureJitCompiled(Class.forName("NullLocks"), "run");

        Main m = new Main();

        m.recursiveSync(0);

        m.nestedMayThrow(false);
        try {
            m.nestedMayThrow(true);
            System.out.println("nestedThrow(true) did not throw");
        } catch (MyException me) {}
        System.out.println("nestedMayThrow ok");

        m.constantLock();
        System.out.println("constantLock ok");

        m.notExcessiveNesting();

        m.notNested();
        System.out.println("notNested ok");

        Object obj1 = new Object();
        Object obj2 = new Object();

        TwoPath.twoPath(obj1, obj2, 0);
        System.out.println("twoPath ok");

        m.triplet(obj1, obj2, 0);
        System.out.println("triplet ok");

        runSmaliTests();
    }

    /**
     * Recursive synchronized method.
     */
    synchronized void recursiveSync(int iter) {
        assertIsManaged();
        if (iter < 40) {
            recursiveSync(iter+1);
        } else {
            System.out.println("recursiveSync ok");
        }
    }

    /**
     * Tests simple nesting, with and without a throw.
     */
    void nestedMayThrow(boolean doThrow) {
        assertIsManaged();
        synchronized (this) {
            synchronized (Main.class) {
                synchronized (new Object()) {
                    synchronized(Class.class) {
                        if (doThrow) {
                            throw new MyException();
                        }
                    }
                }
            }
        }
    }

    /**
     * Exercises bug 3215458.
     */
    void constantLock() {
        assertIsManaged();
        Class<?> thing = Thread.class;
        synchronized (Thread.class) {}
    }

    /**
     * Confirms that we can have 32 nested monitors on one method.
     */
    void notExcessiveNesting() {
        // clang-format off
        assertIsManaged();
        synchronized (this) {   // 1
        synchronized (this) {   // 2
        synchronized (this) {   // 3
        synchronized (this) {   // 4
        synchronized (this) {   // 5
        synchronized (this) {   // 6
        synchronized (this) {   // 7
        synchronized (this) {   // 8
        synchronized (this) {   // 9
        synchronized (this) {   // 10
        synchronized (this) {   // 11
        synchronized (this) {   // 12
        synchronized (this) {   // 13
        synchronized (this) {   // 14
        synchronized (this) {   // 15
        synchronized (this) {   // 16
        synchronized (this) {   // 17
        synchronized (this) {   // 18
        synchronized (this) {   // 19
        synchronized (this) {   // 20
        synchronized (this) {   // 21
        synchronized (this) {   // 22
        synchronized (this) {   // 23
        synchronized (this) {   // 24
        synchronized (this) {   // 25
        synchronized (this) {   // 26
        synchronized (this) {   // 27
        synchronized (this) {   // 28
        synchronized (this) {   // 29
        synchronized (this) {   // 30
        synchronized (this) {   // 31
        synchronized (this) {   // 32
        }}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}
        // clang-format on
    }

    /**
     * Confirms that we can have more than 32 non-nested monitors in one
     * method.
     */
    void notNested() {
        // clang-format off
        assertIsManaged();
        synchronized (this) {}  // 1
        synchronized (this) {}  // 2
        synchronized (this) {}  // 3
        synchronized (this) {}  // 4
        synchronized (this) {}  // 5
        synchronized (this) {}  // 6
        synchronized (this) {}  // 7
        synchronized (this) {}  // 8
        synchronized (this) {}  // 9
        synchronized (this) {}  // 10
        synchronized (this) {}  // 11
        synchronized (this) {}  // 12
        synchronized (this) {}  // 13
        synchronized (this) {}  // 14
        synchronized (this) {}  // 15
        synchronized (this) {}  // 16
        synchronized (this) {}  // 17
        synchronized (this) {}  // 18
        synchronized (this) {}  // 19
        synchronized (this) {}  // 20
        synchronized (this) {}  // 21
        synchronized (this) {}  // 22
        synchronized (this) {}  // 23
        synchronized (this) {}  // 24
        synchronized (this) {}  // 25
        synchronized (this) {}  // 26
        synchronized (this) {}  // 27
        synchronized (this) {}  // 28
        synchronized (this) {}  // 29
        synchronized (this) {}  // 30
        synchronized (this) {}  // 31
        synchronized (this) {}  // 32
        synchronized (this) {}  // 33
        synchronized (this) {}  // 34
        // clang-format on
    }

    /* does nothing but ensure that the compiler doesn't discard an object */
    private void doNothing(Object obj) {}

    /**
     * Lock the monitor two or three times, and make use of the locked or
     * unlocked object.
     */
    public void triplet(Object obj1, Object obj2, int x) {
        Object localObj;

        synchronized (obj1) {
            synchronized(obj1) {
                if (x == 0) {
                    synchronized(obj1) {
                        localObj = obj2;
                    }
                } else {
                    localObj = obj1;
                }
            }
        }

        doNothing(localObj);
    }

    // Smali testing code.
    private static void runSmaliTests() {
        runTest("OK", new Object[] { new Object(), new Object() }, null);
        runTest("TooDeep", new Object[] { new Object() }, null);
        runTest("NotStructuredOverUnlock", new Object[] { new Object() },
                IllegalMonitorStateException.class);
        runTest("NotStructuredUnderUnlock", new Object[] { new Object() },
                IllegalMonitorStateException.class);
        runTest("UnbalancedJoin", new Object[] { new Object(), new Object() }, null);
        runTest("UnbalancedStraight", new Object[] { new Object(), new Object() }, null);
        runTest("NullLocks", new Object[] { false }, null);
        runTest("NullLocks", new Object[] { true }, NullPointerException.class);
    }

    private static void runTest(String className, Object[] parameters, Class<?> excType) {
        try {
            Class<?> c = Class.forName(className);

            Method[] methods = c.getDeclaredMethods();

            // For simplicity we assume that test methods are not overloaded. So searching by name
            // will give us the method we need to run.
            Method method = null;
            for (Method m : methods) {
                if (m.getName().equals("run")) {
                    method = m;
                    break;
                }
            }

            if (method == null) {
                System.out.println("Could not find test method for " + className);
            } else if (!Modifier.isStatic(method.getModifiers())) {
                System.out.println("Test method for " + className + " is not static.");
            } else {
                method.invoke(null, parameters);
                if (excType != null) {
                    System.out.println("Expected an exception in " + className);
                }
            }
        } catch (Throwable exc) {
            if (excType == null) {
                System.out.println("Did not expect exception " + exc + " for " + className);
                exc.printStackTrace(System.out);
            } else if (exc instanceof InvocationTargetException && exc.getCause() != null &&
                       exc.getCause().getClass().equals(excType)) {
                // Expected exception is wrapped in InvocationTargetException.
            } else if (!excType.equals(exc.getClass())) {
                System.out.println("Expected " + excType.getName() + ", but got " + exc.getClass());
            } else {
              // Expected exception, do nothing.
            }
        }
    }

    // Helpers for the smali code.
    public static native void assertIsInterpreted();
    public static native void assertIsManaged();
    public static native boolean hasOatFile();
    public static native boolean runtimeIsSoftFail();
    public static native boolean isInterpreted();
    public static native void disableStackFrameAsserts();
    private static native void ensureJitCompiled(Class<?> itf, String method_name);
}
