/*
 * Copyright (c) 2023, 2024, 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.classfile.ClassFile;
import jdk.test.lib.util.ForceGC;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;

import java.lang.constant.ClassDesc;
import java.lang.constant.MethodTypeDesc;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandleProxies;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.ref.WeakReference;
import java.util.Comparator;

import static java.lang.constant.ConstantDescs.*;
import static java.lang.invoke.MethodHandleProxies.*;
import static java.lang.invoke.MethodType.methodType;
import static java.lang.classfile.ClassFile.*;
import static org.junit.jupiter.api.Assertions.*;

/*
 * @test
 * @bug 6983726
 * @library /test/lib
 * @summary Tests on implementation hidden classes spinned by MethodHandleProxies
 * @build WrapperHiddenClassTest Client jdk.test.lib.util.ForceGC
 * @run junit WrapperHiddenClassTest
 */
public class WrapperHiddenClassTest {

    /**
     * Tests an adversary "implementation" class will not be
     * "recovered" by the wrapperInstance* APIs
     */
    @Test
    public void testWrapperInstance() throws Throwable {
        Comparator<Integer> hostile = createHostileInstance();
        var mh = MethodHandles.publicLookup()
                .findVirtual(Integer.class, "compareTo", methodType(int.class, Integer.class));
        @SuppressWarnings("unchecked")
        Comparator<Integer> proxy = (Comparator<Integer>) asInterfaceInstance(Comparator.class, mh);

        assertTrue(isWrapperInstance(proxy));
        assertFalse(isWrapperInstance(hostile));
        assertSame(mh, wrapperInstanceTarget(proxy));
        assertThrows(IllegalArgumentException.class, () -> wrapperInstanceTarget(hostile));
        assertSame(Comparator.class, wrapperInstanceType(proxy));
        assertThrows(IllegalArgumentException.class, () -> wrapperInstanceType(hostile));
    }

    private static final String TYPE = "interfaceType";
    private static final String TARGET = "target";
    private static final ClassDesc CD_HostileWrapper = ClassDesc.of("HostileWrapper");
    private static final ClassDesc CD_Comparator = ClassDesc.of("java.util.Comparator");
    private static final MethodTypeDesc MTD_int_Object_Object = MethodTypeDesc.of(CD_int, CD_Object, CD_Object);
    private static final MethodTypeDesc MTD_int_Integer = MethodTypeDesc.of(CD_int, CD_Integer);

    // Update this template when the MHP template is updated
    @SuppressWarnings("unchecked")
    private Comparator<Integer> createHostileInstance() throws Throwable {
        var cf = ClassFile.of();
        var bytes = cf.build(CD_HostileWrapper, clb -> {
            clb.withSuperclass(CD_Object);
            clb.withFlags(ACC_FINAL | ACC_SYNTHETIC);
            clb.withInterfaceSymbols(CD_Comparator);

            // static and instance fields
            clb.withField(TYPE, CD_Class, ACC_PRIVATE | ACC_STATIC | ACC_FINAL);
            clb.withField(TARGET, CD_MethodHandle, ACC_PRIVATE | ACC_FINAL);

            // <clinit>
            clb.withMethodBody(CLASS_INIT_NAME, MTD_void, ACC_STATIC, cob -> {
                cob.loadConstant(CD_Comparator);
                cob.putstatic(CD_HostileWrapper, TYPE, CD_Class);
                cob.return_();
            });

            // <init>
            clb.withMethodBody(INIT_NAME, MTD_void, ACC_PUBLIC, cob -> {
                cob.aload(0);
                cob.invokespecial(CD_Object, INIT_NAME, MTD_void);
                cob.return_();
            });

            // implementation
            clb.withMethodBody("compare", MTD_int_Object_Object, ACC_PUBLIC, cob -> {
                cob.aload(1);
                cob.checkcast(CD_Integer);
                cob.aload(2);
                cob.checkcast(CD_Integer);
                cob.invokestatic(CD_Integer, "compareTo", MTD_int_Integer);
                cob.ireturn();
            });
        });
        var l = MethodHandles.lookup().defineHiddenClass(bytes, true);
        return (Comparator<Integer>) l.findConstructor(l.lookupClass(), MethodType.methodType(void.class)).invoke();
    }

    /**
     * Ensures a user interface cannot access a Proxy implementing it.
     */
    @Test
    public void testNoAccess() {
        var instance = asInterfaceInstance(Client.class, MethodHandles.zero(void.class));
        var instanceClass = instance.getClass();
        var interfaceLookup = Client.lookup();
        assertEquals(MethodHandles.Lookup.ORIGINAL, interfaceLookup.lookupModes() & MethodHandles.Lookup.ORIGINAL,
                "Missing original flag on interface's lookup");
        assertThrows(IllegalAccessException.class, () -> MethodHandles.privateLookupIn(instanceClass,
                interfaceLookup));
    }

    /**
     * Tests the Proxy module properties for Proxies implementing system and
     * user interfaces.
     */
    @ParameterizedTest
    @ValueSource(classes = {Client.class, Runnable.class})
    public void testModule(Class<?> ifaceClass) {
        var mh = MethodHandles.zero(void.class);

        var inst = asInterfaceInstance(ifaceClass, mh);
        Module ifaceModule = ifaceClass.getModule();
        Class<?> implClass = inst.getClass();
        Module implModule = implClass.getModule();

        String implPackage = implClass.getPackageName();
        assertFalse(implModule.isExported(implPackage),
                "implementation should not be exported");
        assertTrue(ifaceModule.isExported(ifaceClass.getPackageName(), implModule),
                "interface package should be exported to implementation");
        assertTrue(implModule.isOpen(implPackage, MethodHandleProxies.class.getModule()),
                "implementation class is not reflectively open to MHP class");
        assertTrue(implModule.isNamed(), "dynamic module must be named");
        assertTrue(implModule.getName().startsWith("jdk.MHProxy"),
                () -> "incorrect dynamic module name: " + implModule.getName());

        assertSame(ifaceClass.getClassLoader(), implClass.getClassLoader(),
                "wrapper class should use the interface's loader ");
        assertSame(implClass.getClassLoader(), implModule.getClassLoader(),
                "module class loader should be wrapper class's loader");
    }

    /**
     * Tests the access control of Proxies implementing system and user
     * interfaces.
     */
    @ParameterizedTest
    @ValueSource(classes = {Client.class, Runnable.class})
    public void testNoInstantiation(Class<?> ifaceClass) throws ReflectiveOperationException {
        var mh = MethodHandles.zero(void.class);
        var instanceClass = asInterfaceInstance(ifaceClass, mh).getClass();
        var ctor = instanceClass.getDeclaredConstructor(MethodHandles.Lookup.class, MethodHandle.class, MethodHandle.class);

        assertThrows(IllegalAccessException.class, () -> ctor.newInstance(Client.lookup(), mh, mh));
        assertThrows(IllegalAccessException.class, () -> ctor.newInstance(MethodHandles.lookup(), mh, mh));
        assertThrows(IllegalAccessException.class, () -> ctor.newInstance(MethodHandles.publicLookup(), mh, mh));
    }

    /**
     * Tests the caching and weak reference of implementation classes for
     * system and user interfaces.
     */
    @ParameterizedTest
    @ValueSource(classes = {Runnable.class, Client.class})
    public void testWeakImplClass(Class<?> ifaceClass) {
        var mh = MethodHandles.zero(void.class);

        var wrapper1 = asInterfaceInstance(ifaceClass, mh);
        var implClass = wrapper1.getClass();

        System.gc(); // helps debug if incorrect items are weakly referenced
        var wrapper2 = asInterfaceInstance(ifaceClass, mh);
        assertSame(implClass, wrapper2.getClass(),
                "MHP should reuse old implementation class when available");

        var implClassRef = new WeakReference<>(implClass);
        // clear strong references
        implClass = null;
        wrapper1 = null;
        wrapper2 = null;

        if (!ForceGC.wait(() -> implClassRef.refersTo(null))) {
            fail("MHP impl class cannot be cleared by GC");
        }
    }
}
