/*
 * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

/* @test
 * @summary unit tests for method handles which permute their arguments
 * @run junit test.java.lang.invoke.ThrowExceptionsTest
 */

package test.java.lang.invoke;

import org.junit.*;

import java.util.*;
import java.lang.reflect.*;

import java.lang.invoke.*;
import static java.lang.invoke.MethodHandles.*;
import static java.lang.invoke.MethodType.*;

public class ThrowExceptionsTest {
    private static final Class CLASS = ThrowExceptionsTest.class;
    private static final Lookup LOOKUP = lookup();

    public static void main(String argv[]) throws Throwable {
        new ThrowExceptionsTest().testAll((argv.length == 0 ? null : Arrays.asList(argv).toString()));
    }

    @Test
    public void testWMT() throws Throwable {
        // mostly call testWMTCallee, but sometimes call its void-returning variant
        MethodHandle mh = testWMTCallee();
        MethodHandle mh1 = mh.asType(mh.type().changeReturnType(void.class));
        assert(mh1 != mh);
        testWMT(mh, mh1, 1000);
    }

    @Test
    public void testBoundWMT() throws Throwable {
        // mostly call exactInvoker.bindTo(testWMTCallee), but sometimes call its void-returning variant
        MethodHandle callee = testWMTCallee();
        MethodHandle callee1 = callee.asType(callee.type().changeReturnType(void.class));
        MethodHandle invoker = exactInvoker(callee.type());
        MethodHandle mh  = invoker.bindTo(callee);
        MethodHandle mh1 = invoker.bindTo(callee1);
        testWMT(mh, mh1, 1000);
    }

    @Test
    public void testFoldWMT() throws Throwable {
        // mostly call exactInvoker.fold(constant(testWMTCallee)), but sometimes call its void-returning variant
        MethodHandle callee = testWMTCallee();
        MethodHandle callee1 = callee.asType(callee.type().changeReturnType(void.class));
        MethodHandle invoker = exactInvoker(callee.type());
        MethodHandle mh  = foldArguments(invoker, constant(MethodHandle.class, callee));
        MethodHandle mh1 = foldArguments(invoker, constant(MethodHandle.class, callee1));
        testWMT(mh, mh1, 1000);
    }

    @Test
    public void testFoldCCE() throws Throwable {
        MethodHandle callee = testWMTCallee();
        MethodHandle callee1 = callee.asType(callee.type().changeParameterType(1, Number.class)).asType(callee.type());
        MethodHandle invoker = exactInvoker(callee.type());
        MethodHandle mh  = foldArguments(invoker, constant(MethodHandle.class, callee));
        MethodHandle mh1 = foldArguments(invoker, constant(MethodHandle.class, callee1));
        testWMT(mh, mh1, 1000);
    }

    @Test
    public void testStackOverflow() throws Throwable {
        MethodHandle callee = testWMTCallee();
        MethodHandle callee1 = makeStackOverflow().asType(callee.type());
        MethodHandle invoker = exactInvoker(callee.type());
        MethodHandle mh  = foldArguments(invoker, constant(MethodHandle.class, callee));
        MethodHandle mh1 = foldArguments(invoker, constant(MethodHandle.class, callee1));
        for (int i = 0; i < REPEAT; i++) {
            try {
                testWMT(mh, mh1, 1000);
            } catch (StackOverflowError ex) {
                // OK, try again
            }
        }
    }

    private static MethodHandle makeStackOverflow() {
        MethodType cellType = methodType(void.class);
        MethodHandle[] cell = { null };  // recursion point
        MethodHandle getCell = insertArguments(arrayElementGetter(cell.getClass()), 0, cell, 0);
        MethodHandle invokeCell = foldArguments(exactInvoker(cellType), getCell);
        assert(invokeCell.type() == cellType);
        cell[0] = invokeCell;
        // make it conformable to any type:
        invokeCell = dropArguments(invokeCell, 0, Object[].class).asVarargsCollector(Object[].class);
        return invokeCell;
    }

    static int testCases;

    private void testAll(String match) throws Throwable {
        testCases = 0;
        Lookup lookup = lookup();
        for (Method m : CLASS.getDeclaredMethods()) {
            String name = m.getName();
            if (name.startsWith("test") &&
                (match == null || match.contains(name.substring("test".length()))) &&
                m.getParameterTypes().length == 0 &&
                Modifier.isPublic(m.getModifiers()) &&
                !Modifier.isStatic(m.getModifiers())) {
                System.out.println("["+name+"]");
                int tc = testCases;
                try {
                    m.invoke(this);
                } catch (Throwable ex) {
                    System.out.println("*** "+ex);
                    ex.printStackTrace();
                }
                if (testCases == tc)  testCases++;
            }
        }
        if (testCases == 0)  throw new RuntimeException("no test cases found");
        System.out.println("ran a total of "+testCases+" test cases");
    }

    private static MethodHandle findStatic(String name) {
        return findMethod(name, true);
    }
    private static MethodHandle findVirtual(String name) {
        return findMethod(name, false);
    }
    private static MethodHandle findMethod(String name, boolean isStatic) {
        MethodHandle mh = null;
        for (Method m : CLASS.getDeclaredMethods()) {
            if (m.getName().equals(name) &&
                Modifier.isStatic(m.getModifiers()) == isStatic) {
                if (mh != null)
                    throw new RuntimeException("duplicate methods: "+name);
                try {
                    mh = LOOKUP.unreflect(m);
                } catch (ReflectiveOperationException ex) {
                    throw new RuntimeException(ex);
                }
            }
        }
        if (mh == null)
            throw new RuntimeException("no method: "+name);
        return mh;
    }

    int testWMTCallee;
    private int testWMTCallee(String x) {
        return testWMTCallee++;
    }
    private static MethodHandle testWMTCallee() {
        MethodHandle callee = findVirtual("testWMTCallee");
        // FIXME: should not have to retype callee
        callee = callee.asType(callee.type().changeParameterType(0, Object.class));
        return callee;
    }

    private Exception testWMT(MethodHandle[] mhs, int reps) throws Throwable {
        testCases += 1;
        testWMTCallee = 0;
        int catches = 0;
        Exception savedEx = null;
        for (int i = 0; i < reps; i++) {
            MethodHandle mh = mhs[i % mhs.length];
            int n;
            try {
                // FIXME: should not have to retype this
                n = (int) mh.invokeExact((Object)this, "x");
                assertEquals(n, i - catches);
                // Using the exact type for this causes endless deopt due to
                // 'non_cached_result' in SystemDictionary::find_method_handle_invoke.
                // The problem is that the compiler thread needs to access a cached
                // invoke method, but invoke methods are not cached if one of the
                // component types is not on the BCP.
            } catch (Exception ex) {
                savedEx = ex;
                catches++;
            }
        }
        //VERBOSE: System.out.println("reps="+reps+" catches="+catches);
        return savedEx;
    }

    private static final int REPEAT = Integer.getInteger(CLASS.getSimpleName()+".REPEAT", 10);

    private Exception testWMT(MethodHandle mh, MethodHandle mh1, int reps) throws Throwable {
        //VERBOSE: System.out.println("mh="+mh+" mh1="+mh1);
        MethodHandle[] mhs = new MethodHandle[100];
        Arrays.fill(mhs, mh);
        int patch = mhs.length-1;
        Exception savedEx = null;
        for (int i = 0; i < REPEAT; i++) {
            mhs[patch] = mh;
            testWMT(mhs, 10000);
            mhs[patch] = mh1;
            savedEx = testWMT(mhs, reps);
        }
        return savedEx;
    }

   private static void assertEquals(Object x, Object y) {
        if (x == y || x != null && x.equals(y))  return;
        throw new RuntimeException(x+" != "+y);
    }
}
