/*
 * Copyright (c) 2017, 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.
 *
 * 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
 * @bug 8157246
 * @summary Tests invocation of MethodHandle with invalid leading argument
 * @run testng/othervm test.java.lang.invoke.InvokeMethodHandleWithBadArgument
 */

package test.java.lang.invoke;

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodHandles.Lookup;
import java.lang.invoke.MethodType;
import java.lang.invoke.VarHandle;

import static java.lang.invoke.MethodType.methodType;

import static org.testng.AssertJUnit.*;

import org.testng.annotations.*;

/**
 * Tests invocation of MethodHandle with invalid leading argument such as
 * MethodHandle, VarHandle, and array object
 */
public class InvokeMethodHandleWithBadArgument {
    // ---- null array reference ----

    @Test(expectedExceptions = {NullPointerException.class})
    public static void testAsSpreaderPosInvokeWithNull() throws Throwable {
        MethodHandle spreader = MH_spread.asSpreader(1, int[].class, 3);
        spreader.invoke("A", null, "B");
    }

    @Test(expectedExceptions = {NullPointerException.class})
    public static void testAsSpreaderInvokeWithNull() throws Throwable {
        MethodHandle spreader = MH_String_equals.asSpreader(String[].class, 2);
        assert ((boolean) spreader.invokeExact(new String[]{"me", "me"}));
        boolean eq = (boolean) spreader.invokeExact((String[]) null);
    }

    // ---- incorrect array element count ----
    @Test(expectedExceptions = {IllegalArgumentException.class})
    public static void testAsSpreaderPosInvokeWithBadElementCount() throws Throwable {
        MethodHandle spreader = MH_spread.asSpreader(1, int[].class, 3);
        spreader.invoke("A", new int[]{1, 2}, "B");
    }

    @Test(expectedExceptions = {IllegalArgumentException.class})
    public static void testAsSpreaderInvokeWithBadElementCount() throws Throwable {
        MethodHandle spreader = MH_String_equals.asSpreader(String[].class, 2);
        assert (!(boolean) spreader.invokeExact(new String[]{"me", "thee"}));
        boolean eq = (boolean) spreader.invokeExact(new String[0]);
    }

    // ---- spread no argument ----
    @Test
    public static void testAsSpreaderPosInvokeWithZeroLength() throws Throwable {
        MethodHandle spreader = MH_spread.asSpreader(1, int[].class, 0);
        assert("A123B".equals(spreader.invoke("A", (int[])null, 1, 2, 3, "B")));
    }

    @Test
    public static void testAsSpreaderInvokeWithZeroLength() throws Throwable {
        MethodHandle spreader = MH_String_equals.asSpreader(String[].class, 0);
        assert ((boolean) spreader.invokeExact("me", (Object)"me", new String[0]));
        boolean eq = (boolean) spreader.invokeExact("me", (Object)"me", (String[]) null);
    }

    // ---- invokers with null method/var handle argument ----
    @Test(expectedExceptions = {NullPointerException.class})
    public static void testInvokerWithNull() throws Throwable {
        MethodType type = methodType(int.class, int.class, int.class);
        MethodHandle invoker = MethodHandles.invoker(type);
        assert((int) invoker.invoke(MH_add, 1, 2) == 3);
        int sum = (int)invoker.invoke((MethodHandle)null, 1, 2);
    }

    @Test(expectedExceptions = {NullPointerException.class})
    public static void testExactInvokerWithNull() throws Throwable {
        MethodType type = methodType(int.class, int.class, int.class);
        MethodHandle invoker = MethodHandles.exactInvoker(type);
        assert((int) invoker.invoke(MH_add, 1, 2) == 3);
        int sum = (int)invoker.invokeExact((MethodHandle)null, 1, 2);
    }

    @Test(expectedExceptions = {NullPointerException.class})
    public static void testSpreadInvokerWithNull() throws Throwable {
        MethodType type = methodType(boolean.class, String.class, String.class);
        MethodHandle invoker = MethodHandles.spreadInvoker(type, 0);
        assert ((boolean) invoker.invoke(MH_String_equals, new String[]{"me", "me"}));
        boolean eq = (boolean) invoker.invoke((MethodHandle)null, new String[]{"me", "me"});
    }

    @Test(expectedExceptions = {NullPointerException.class})
    public static void testVarHandleInvokerWithNull() throws Throwable {
        VarHandle.AccessMode am = VarHandle.AccessMode.GET;
        MethodHandle invoker = MethodHandles.varHandleInvoker(am, VH_array.accessModeType(am));
        assert ((int) invoker.invoke(VH_array, array, 3) == 3);
        int value = (int)invoker.invoke((VarHandle)null, array, 3);
    }

    @Test(expectedExceptions = {NullPointerException.class})
    public static void testVarHandleExactInvokerWithNull() throws Throwable {
        VarHandle.AccessMode am = VarHandle.AccessMode.GET;
        MethodHandle invoker = MethodHandles.varHandleExactInvoker(am, VH_array.accessModeType(am));
        assert ((int) invoker.invoke(VH_array, array, 3) == 3);
        int value = (int)invoker.invokeExact((VarHandle)null, array, 3);
    }

    static final Lookup LOOKUP = MethodHandles.lookup();
    static final MethodHandle MH_add;
    static final MethodHandle MH_spread;
    static final MethodHandle MH_String_equals;
    static final VarHandle VH_array;

    static final int[] array = new int[] { 0, 1, 2, 3, 4, 5};
    static {
        try {
            Class<?> arrayClass = Class.forName("[I");
            VH_array = MethodHandles.arrayElementVarHandle(arrayClass);
            MH_add = LOOKUP.findStatic(InvokeMethodHandleWithBadArgument.class, "add",
                methodType(int.class, int.class, int.class));
            MH_spread = LOOKUP.findStatic(InvokeMethodHandleWithBadArgument.class, "spread",
                methodType(String.class, String.class, int.class, int.class, int.class, String.class));
            MH_String_equals = LOOKUP.findVirtual(String.class, "equals", methodType(boolean.class, Object.class));
        } catch (Exception e) {
            throw new ExceptionInInitializerError(e);
        }
    }

    static String spread(String s1, int i1, int i2, int i3, String s2) {
        return s1 + i1 + i2 + i3 + s2;
    }

    static int add(int x, int y) {
        return x+y;
    }
}
