/*
 * Copyright (c) 2018, 2023, 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.
 */

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandleInfo;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.invoke.WrongMethodTypeException;
import java.lang.constant.ClassDesc;
import java.lang.constant.ConstantDescs;
import java.lang.constant.DirectMethodHandleDesc;
import java.lang.constant.MethodHandleDesc;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.lang.constant.MethodTypeDesc;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Supplier;

import org.testng.annotations.Test;

import static java.lang.constant.ConstantDescs.CD_Void;
import static java.lang.constant.ConstantDescs.CD_boolean;
import static java.lang.constant.DirectMethodHandleDesc.*;
import static java.lang.constant.DirectMethodHandleDesc.Kind.GETTER;
import static java.lang.constant.DirectMethodHandleDesc.Kind.SETTER;
import static java.lang.constant.DirectMethodHandleDesc.Kind.STATIC_GETTER;
import static java.lang.constant.DirectMethodHandleDesc.Kind.STATIC_SETTER;
import static java.lang.constant.DirectMethodHandleDesc.Kind.VIRTUAL;
import static java.lang.constant.ConstantDescs.CD_Integer;
import static java.lang.constant.ConstantDescs.CD_List;
import static java.lang.constant.ConstantDescs.CD_Object;
import static java.lang.constant.ConstantDescs.CD_String;
import static java.lang.constant.ConstantDescs.CD_int;
import static java.lang.constant.ConstantDescs.CD_void;
import static java.lang.invoke.MethodHandleInfo.*;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotEquals;
import static org.testng.Assert.assertNotSame;
import static org.testng.Assert.assertSame;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;

/**
 * @test
 * @compile MethodHandleDescTest.java
 * @run testng MethodHandleDescTest
 * @summary unit tests for java.lang.constant.MethodHandleDesc
 */
@Test
public class MethodHandleDescTest extends SymbolicDescTest {
    private static ClassDesc helperHolderClass = ClassDesc.of("TestHelpers");
    private static ClassDesc testClass = helperHolderClass.nested("TestClass");
    private static ClassDesc testInterface = helperHolderClass.nested("TestInterface");
    private static ClassDesc testSuperclass = helperHolderClass.nested("TestSuperclass");


    private static void assertMHEquals(MethodHandle a, MethodHandle b) {
        MethodHandleInfo ia = LOOKUP.revealDirect(a);
        MethodHandleInfo ib = LOOKUP.revealDirect(b);
        assertEquals(ia.getDeclaringClass(), ib.getDeclaringClass());
        assertEquals(ia.getName(), ib.getName());
        assertEquals(ia.getMethodType(), ib.getMethodType());
        assertEquals(ia.getReferenceKind(), ib.getReferenceKind());
    }

    private void testMethodHandleDesc(MethodHandleDesc r) throws ReflectiveOperationException {
        if (r instanceof DirectMethodHandleDesc) {
            testSymbolicDesc(r);

            DirectMethodHandleDesc rr = (DirectMethodHandleDesc) r;
            assertEquals(r, MethodHandleDesc.of(rr.kind(), rr.owner(), rr.methodName(), rr.lookupDescriptor()));
            assertEquals(r.invocationType().resolveConstantDesc(LOOKUP), r.resolveConstantDesc(LOOKUP).type());
        }
        else {
            testSymbolicDescForwardOnly(r);
        }
    }

    private String lookupDescriptor(DirectMethodHandleDesc rr) {
        switch (rr.kind()) {
            case VIRTUAL:
            case SPECIAL:
            case INTERFACE_VIRTUAL:
            case INTERFACE_SPECIAL:
                return rr.invocationType().dropParameterTypes(0, 1).descriptorString();
            case CONSTRUCTOR:
                return rr.invocationType().changeReturnType(CD_void).descriptorString();
            default:
                return rr.invocationType().descriptorString();
        }
    }

    private void testMethodHandleDesc(MethodHandleDesc r, MethodHandle mh) throws ReflectiveOperationException {
        testMethodHandleDesc(r);

        assertMHEquals(r.resolveConstantDesc(LOOKUP), mh);
        assertEquals(mh.describeConstable().orElseThrow(), r);

        // compare extractable properties: refKind, owner, name, type
        MethodHandleInfo mhi = LOOKUP.revealDirect(mh);
        DirectMethodHandleDesc rr = (DirectMethodHandleDesc) r;
        assertEquals(mhi.getDeclaringClass().descriptorString(), rr.owner().descriptorString());
        assertEquals(mhi.getName(), rr.methodName());
        assertEquals(mhi.getReferenceKind(), rr.kind().refKind);
        MethodType type = mhi.getMethodType();
        assertEquals(type.toMethodDescriptorString(), lookupDescriptor(rr));
    }

    public void testSimpleMHs() throws ReflectiveOperationException {
        MethodHandle MH_String_isEmpty = LOOKUP.findVirtual(String.class, "isEmpty", MethodType.fromMethodDescriptorString("()Z", null));
        testMethodHandleDesc(MethodHandleDesc.of(Kind.VIRTUAL, CD_String, "isEmpty", "()Z"), MH_String_isEmpty);
        testMethodHandleDesc(MethodHandleDesc.ofMethod(Kind.VIRTUAL, CD_String, "isEmpty", MethodTypeDesc.of(CD_boolean)), MH_String_isEmpty);

        MethodHandle MH_List_isEmpty = LOOKUP.findVirtual(List.class, "isEmpty", MethodType.fromMethodDescriptorString("()Z", null));
        testMethodHandleDesc(MethodHandleDesc.of(Kind.INTERFACE_VIRTUAL, CD_List, "isEmpty", "()Z"), MH_List_isEmpty);
        testMethodHandleDesc(MethodHandleDesc.ofMethod(Kind.INTERFACE_VIRTUAL, CD_List, "isEmpty", MethodTypeDesc.of(CD_boolean)), MH_List_isEmpty);

        MethodHandle MH_String_format = LOOKUP.findStatic(String.class, "format", MethodType.methodType(String.class, String.class, Object[].class));
        testMethodHandleDesc(MethodHandleDesc.of(Kind.STATIC, CD_String, "format", MethodType.methodType(String.class, String.class, Object[].class).descriptorString()),
                             MH_String_format);
        testMethodHandleDesc(MethodHandleDesc.ofMethod(Kind.STATIC, CD_String, "format", MethodTypeDesc.of(CD_String, CD_String, CD_Object.arrayType())),
                             MH_String_format);

        MethodHandle MH_ArrayList_new = LOOKUP.findConstructor(ArrayList.class, MethodType.methodType(void.class));
        testMethodHandleDesc(MethodHandleDesc.ofMethod(Kind.CONSTRUCTOR, ClassDesc.of("java.util.ArrayList"), "<init>", MethodTypeDesc.of(CD_void)),
                             MH_ArrayList_new);
        testMethodHandleDesc(MethodHandleDesc.ofConstructor(ClassDesc.of("java.util.ArrayList")), MH_ArrayList_new);

        // bad constructor non void return type
        try {
            MethodHandleDesc.of(Kind.CONSTRUCTOR, ClassDesc.of("java.util.ArrayList"), "<init>", "()I");
            fail("should have failed: non void return type for constructor");
        } catch (IllegalArgumentException ex) {
            // good
        }

        // null list of parameters
        try {
            MethodHandleDesc.ofConstructor(ClassDesc.of("java.util.ArrayList", null));
            fail("should have failed: null list of parameters");
        } catch (NullPointerException ex) {
            // good
        }

        // null elements in list of parameters
        try {
            ClassDesc[] paramList = new ClassDesc[1];
            paramList[0] = null;
            MethodHandleDesc.ofConstructor(ClassDesc.of("java.util.ArrayList"), paramList);
            fail("should have failed: null content in list of parameters");
        } catch (NullPointerException ex) {
            // good
        }
    }

    public void testAsType() throws Throwable {
        MethodHandleDesc mhr = MethodHandleDesc.ofMethod(Kind.STATIC, ClassDesc.of("java.lang.Integer"), "valueOf",
                                                         MethodTypeDesc.of(CD_Integer, CD_int));
        MethodHandleDesc takesInteger = mhr.asType(MethodTypeDesc.of(CD_Integer, CD_Integer));
        testMethodHandleDesc(takesInteger);
        MethodHandle mh1 = takesInteger.resolveConstantDesc(LOOKUP);
        assertEquals((Integer) 3, (Integer) mh1.invokeExact((Integer) 3));
        assertEquals(takesInteger.toString(), "MethodHandleDesc[STATIC/Integer::valueOf(int)Integer].asType(Integer)Integer");

        try {
            Integer i = (Integer) mh1.invokeExact(3);
            fail("Expected WMTE");
        }
        catch (WrongMethodTypeException ignored) { }

        MethodHandleDesc takesInt = takesInteger.asType(MethodTypeDesc.of(CD_Integer, CD_int));
        testMethodHandleDesc(takesInt);
        MethodHandle mh2 = takesInt.resolveConstantDesc(LOOKUP);
        assertEquals((Integer) 3, (Integer) mh2.invokeExact(3));

        try {
            Integer i = (Integer) mh2.invokeExact((Integer) 3);
            fail("Expected WMTE");
        }
        catch (WrongMethodTypeException ignored) { }

        // Short circuit optimization
        MethodHandleDesc same = mhr.asType(mhr.invocationType());
        assertSame(mhr, same);

        try {
            mhr.asType(null);
            fail("Expected NPE");
        } catch (NullPointerException ex) {
            // good
        }

        // @@@ Test varargs adaptation
        // @@@ Test bad adaptations and assert runtime error on resolution
        // @@@ Test intrinsification of adapted MH
    }

    public void testMethodHandleDesc() throws Throwable {
        MethodHandleDesc ctorDesc = MethodHandleDesc.of(Kind.CONSTRUCTOR, testClass, "<ignored!>", "()V");
        MethodHandleDesc staticMethodDesc = MethodHandleDesc.of(Kind.STATIC, testClass, "sm", "(I)I");
        MethodHandleDesc staticIMethodDesc = MethodHandleDesc.of(Kind.INTERFACE_STATIC, testInterface, "sm", "(I)I");
        MethodHandleDesc instanceMethodDesc = MethodHandleDesc.of(Kind.VIRTUAL, testClass, "m", "(I)I");
        MethodHandleDesc instanceIMethodDesc = MethodHandleDesc.of(Kind.INTERFACE_VIRTUAL, testInterface, "m", "(I)I");
        MethodHandleDesc superMethodDesc = MethodHandleDesc.of(Kind.SPECIAL, testSuperclass, "m", "(I)I");
        MethodHandleDesc superIMethodDesc = MethodHandleDesc.of(Kind.INTERFACE_SPECIAL, testInterface, "m", "(I)I");
        MethodHandleDesc privateMethodDesc = MethodHandleDesc.of(Kind.SPECIAL, testClass, "pm", "(I)I");
        MethodHandleDesc privateIMethodDesc = MethodHandleDesc.of(Kind.INTERFACE_SPECIAL, testInterface, "pm", "(I)I");
        MethodHandleDesc privateStaticMethodDesc = MethodHandleDesc.of(Kind.STATIC, testClass, "psm", "(I)I");
        MethodHandleDesc privateStaticIMethodDesc = MethodHandleDesc.of(Kind.INTERFACE_STATIC, testInterface, "psm", "(I)I");

        assertEquals(ctorDesc.invocationType(), MethodTypeDesc.of(testClass));
        assertEquals(((DirectMethodHandleDesc) ctorDesc).lookupDescriptor(), "()V");

        assertEquals(staticMethodDesc.invocationType().descriptorString(), "(I)I");
        assertEquals(((DirectMethodHandleDesc) staticMethodDesc).lookupDescriptor(), "(I)I");

        assertEquals(instanceMethodDesc.invocationType().descriptorString(), "(" + testClass.descriptorString() + "I)I");
        assertEquals(((DirectMethodHandleDesc) instanceMethodDesc).lookupDescriptor(), "(I)I");

        for (MethodHandleDesc r : List.of(ctorDesc, staticMethodDesc, staticIMethodDesc, instanceMethodDesc, instanceIMethodDesc))
            testMethodHandleDesc(r);

        TestHelpers.TestClass instance = (TestHelpers.TestClass) ctorDesc.resolveConstantDesc(LOOKUP).invokeExact();
        TestHelpers.TestClass instance2 = (TestHelpers.TestClass) ctorDesc.resolveConstantDesc(TestHelpers.TestClass.LOOKUP).invokeExact();
        TestHelpers.TestInterface instanceI = instance;

        assertNotSame(instance, instance2);

        assertEquals(5, (int) staticMethodDesc.resolveConstantDesc(LOOKUP).invokeExact(5));
        assertEquals(5, (int) staticMethodDesc.resolveConstantDesc(TestHelpers.TestClass.LOOKUP).invokeExact(5));
        assertEquals(0, (int) staticIMethodDesc.resolveConstantDesc(LOOKUP).invokeExact(5));
        assertEquals(0, (int) staticIMethodDesc.resolveConstantDesc(TestHelpers.TestClass.LOOKUP).invokeExact(5));

        assertEquals(5, (int) instanceMethodDesc.resolveConstantDesc(LOOKUP).invokeExact(instance, 5));
        assertEquals(5, (int) instanceMethodDesc.resolveConstantDesc(TestHelpers.TestClass.LOOKUP).invokeExact(instance, 5));
        assertEquals(5, (int) instanceIMethodDesc.resolveConstantDesc(LOOKUP).invokeExact(instanceI, 5));
        assertEquals(5, (int) instanceIMethodDesc.resolveConstantDesc(TestHelpers.TestClass.LOOKUP).invokeExact(instanceI, 5));

        try { superMethodDesc.resolveConstantDesc(LOOKUP); fail(); }
        catch (IllegalAccessException e) { /* expected */ }
        assertEquals(-1, (int) superMethodDesc.resolveConstantDesc(TestHelpers.TestClass.LOOKUP).invokeExact(instance, 5));

        try { superIMethodDesc.resolveConstantDesc(LOOKUP); fail(); }
        catch (IllegalAccessException e) { /* expected */ }
        assertEquals(0, (int) superIMethodDesc.resolveConstantDesc(TestHelpers.TestClass.LOOKUP).invokeExact(instance, 5));

        try { privateMethodDesc.resolveConstantDesc(LOOKUP); fail(); }
        catch (IllegalAccessException e) { /* expected */ }
        assertEquals(5, (int) privateMethodDesc.resolveConstantDesc(TestHelpers.TestClass.LOOKUP).invokeExact(instance, 5));

        try { privateIMethodDesc.resolveConstantDesc(LOOKUP); fail(); }
        catch (IllegalAccessException e) { /* expected */ }
        assertEquals(0, (int) privateIMethodDesc.resolveConstantDesc(TestHelpers.TestInterface.LOOKUP).invokeExact(instanceI, 5));
        assertEquals(0, (int) privateIMethodDesc.resolveConstantDesc(TestHelpers.TestClass.LOOKUP).invoke(instanceI, 5));

        try { privateStaticMethodDesc.resolveConstantDesc(LOOKUP); fail(); }
        catch (IllegalAccessException e) { /* expected */ }
        assertEquals(5, (int) privateStaticMethodDesc.resolveConstantDesc(TestHelpers.TestClass.LOOKUP).invokeExact(5));

        try { privateStaticIMethodDesc.resolveConstantDesc(LOOKUP); fail(); }
        catch (IllegalAccessException e) { /* expected */ }
        assertEquals(0, (int) privateStaticIMethodDesc.resolveConstantDesc(TestHelpers.TestInterface.LOOKUP).invokeExact(5));
        assertEquals(0, (int) privateStaticIMethodDesc.resolveConstantDesc(TestHelpers.TestClass.LOOKUP).invokeExact(5));

        MethodHandleDesc staticSetterDesc = MethodHandleDesc.ofField(STATIC_SETTER, testClass, "sf", CD_int);
        MethodHandleDesc staticGetterDesc = MethodHandleDesc.ofField(STATIC_GETTER, testClass, "sf", CD_int);
        MethodHandleDesc staticGetterIDesc = MethodHandleDesc.ofField(STATIC_GETTER, testInterface, "sf", CD_int);
        MethodHandleDesc setterDesc = MethodHandleDesc.ofField(SETTER, testClass, "f", CD_int);
        MethodHandleDesc getterDesc = MethodHandleDesc.ofField(GETTER, testClass, "f", CD_int);

        for (MethodHandleDesc r : List.of(staticSetterDesc, staticGetterDesc, staticGetterIDesc, setterDesc, getterDesc))
            testMethodHandleDesc(r);

        staticSetterDesc.resolveConstantDesc(LOOKUP).invokeExact(6); assertEquals(TestHelpers.TestClass.sf, 6);
        assertEquals(6, (int) staticGetterDesc.resolveConstantDesc(LOOKUP).invokeExact());
        assertEquals(6, (int) staticGetterDesc.resolveConstantDesc(TestHelpers.TestClass.LOOKUP).invokeExact());
        staticSetterDesc.resolveConstantDesc(TestHelpers.TestClass.LOOKUP).invokeExact(7); assertEquals(TestHelpers.TestClass.sf, 7);
        assertEquals(7, (int) staticGetterDesc.resolveConstantDesc(LOOKUP).invokeExact());
        assertEquals(7, (int) staticGetterDesc.resolveConstantDesc(TestHelpers.TestClass.LOOKUP).invokeExact());

        assertEquals(3, (int) staticGetterIDesc.resolveConstantDesc(LOOKUP).invokeExact());
        assertEquals(3, (int) staticGetterIDesc.resolveConstantDesc(TestHelpers.TestClass.LOOKUP).invokeExact());

        setterDesc.resolveConstantDesc(LOOKUP).invokeExact(instance, 6); assertEquals(instance.f, 6);
        assertEquals(6, (int) getterDesc.resolveConstantDesc(LOOKUP).invokeExact(instance));
        assertEquals(6, (int) getterDesc.resolveConstantDesc(TestHelpers.TestClass.LOOKUP).invokeExact(instance));
        setterDesc.resolveConstantDesc(TestHelpers.TestClass.LOOKUP).invokeExact(instance, 7); assertEquals(instance.f, 7);
        assertEquals(7, (int) getterDesc.resolveConstantDesc(LOOKUP).invokeExact(instance));
        assertEquals(7, (int) getterDesc.resolveConstantDesc(TestHelpers.TestClass.LOOKUP).invokeExact(instance));
    }

    private void assertBadArgs(Supplier<MethodHandleDesc> supplier, String s) {
        try {
            MethodHandleDesc r = supplier.get();
            fail("Expected failure for " + s);
        }
        catch (IllegalArgumentException e) {
            // succeed
        }
    }

    public void testBadFieldMHs() {
        List<String> badGetterDescs = List.of("()V", "(Ljava/lang/Object;)V", "(I)I", "(Ljava/lang/Object;I)I");
        List<String> badStaticGetterDescs = List.of("()V", "(Ljava/lang/Object;)I", "(I)I", "(Ljava/lang/Object;I)I");
        List<String> badSetterDescs = List.of("()V", "(I)V", "(Ljava/lang/Object;)V", "(Ljava/lang/Object;I)I", "(Ljava/lang/Object;II)V");
        List<String> badStaticSetterDescs = List.of("()V", "(II)V", "()I");

        badGetterDescs.forEach(s -> assertBadArgs(() -> MethodHandleDesc.of(GETTER, helperHolderClass, "x", s), s));
        badSetterDescs.forEach(s -> assertBadArgs(() -> MethodHandleDesc.of(SETTER, helperHolderClass, "x", s), s));
        badStaticGetterDescs.forEach(s -> assertBadArgs(() -> MethodHandleDesc.of(STATIC_GETTER, helperHolderClass, "x", s), s));
        badStaticSetterDescs.forEach(s -> assertBadArgs(() -> MethodHandleDesc.of(STATIC_SETTER, helperHolderClass, "x", s), s));
    }

    @Test(expectedExceptions = IllegalArgumentException.class)
    public void testBadOwners() {
        MethodHandleDesc.ofMethod(VIRTUAL, ClassDesc.ofDescriptor("I"), "x", MethodTypeDesc.ofDescriptor("()I"));
    }

    public void testSymbolicDescsConstants() throws ReflectiveOperationException {
        int tested = 0;
        Field[] fields = ConstantDescs.class.getDeclaredFields();
        for (Field f : fields) {
            try {
                if (f.getType().equals(DirectMethodHandleDesc.class)
                    && ((f.getModifiers() & Modifier.STATIC) != 0)
                    && ((f.getModifiers() & Modifier.PUBLIC) != 0)) {
                    MethodHandleDesc r = (MethodHandleDesc) f.get(null);
                    MethodHandle m = r.resolveConstantDesc(MethodHandles.lookup());
                    testMethodHandleDesc(r, m);
                    ++tested;
                }
            }
            catch (Throwable e) {
                fail("Error testing field " + f.getName(), e);
            }
        }

        assertTrue(tested > 0);
    }

    public void testKind() {
        for (Kind k : Kind.values()) {
            assertEquals(Kind.valueOf(k.refKind), Kind.valueOf(k.refKind, k.refKind == MethodHandleInfo.REF_invokeInterface));
            assertEquals(Kind.valueOf(k.refKind, k.isInterface), k);
        }
        // let's now verify those cases for which the value of the isInterface parameter is ignored
        int[] isInterfaceIgnored = new int[] {
                REF_getField,
                REF_getStatic,
                REF_putField,
                REF_putStatic,
                REF_newInvokeSpecial,
                REF_invokeInterface
        };
        for (int refKind : isInterfaceIgnored) {
            assertEquals(Kind.valueOf(refKind, false), Kind.valueOf(refKind, true));
        }

        // some explicit tests for REF_invokeStatic and REF_invokeSpecial
        assertNotEquals(Kind.valueOf(REF_invokeStatic, false), Kind.valueOf(REF_invokeStatic, true));
        assertNotEquals(Kind.valueOf(REF_invokeSpecial, false), Kind.valueOf(REF_invokeSpecial, true));
        assertEquals(Kind.valueOf(REF_invokeStatic, false), Kind.STATIC);
        assertEquals(Kind.valueOf(REF_invokeStatic, true), Kind.INTERFACE_STATIC);
        assertEquals(Kind.valueOf(REF_invokeSpecial, false), Kind.SPECIAL);
        assertEquals(Kind.valueOf(REF_invokeSpecial, true), Kind.INTERFACE_SPECIAL);
    }
}
