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

/*
 * @test
 * @bug 8330467
 * @modules jdk.compiler
 * @library /test/lib
 * @compile BadClassFile.jcod
 *          BadClassFile2.jcod
 *          BadClassFileVersion.jcod
 * @build jdk.test.lib.Utils
 *        jdk.test.lib.compiler.CompilerUtils
 * @run testng/othervm BasicTest
 */

import java.io.File;
import java.io.IOException;
import java.lang.classfile.ClassFile;
import java.lang.constant.ClassDesc;
import java.lang.invoke.MethodHandles.Lookup;
import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;

import jdk.test.lib.compiler.CompilerUtils;
import jdk.test.lib.Utils;

import org.testng.annotations.BeforeTest;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

import static java.lang.classfile.ClassFile.*;
import static java.lang.constant.ConstantDescs.CD_Enum;
import static java.lang.constant.ConstantDescs.CD_Object;
import static java.lang.invoke.MethodHandles.lookup;
import static java.lang.invoke.MethodHandles.Lookup.ClassOption.*;
import static org.testng.Assert.*;

interface HiddenTest {
    void test();
}

public class BasicTest {

    private static final Path SRC_DIR = Paths.get(Utils.TEST_SRC, "src");
    private static final Path CLASSES_DIR = Paths.get("classes");
    private static final Path CLASSES_10_DIR = Paths.get("classes_10");

    private static byte[] hiddenClassBytes;

    @BeforeTest
    static void setup() throws IOException {
        compileSources(SRC_DIR, CLASSES_DIR);
        hiddenClassBytes = Files.readAllBytes(CLASSES_DIR.resolve("HiddenClass.class"));

        // compile with --release 10 with no NestHost and NestMembers attribute
        compileSources(SRC_DIR.resolve("Outer.java"), CLASSES_10_DIR, "--release", "10");
        compileSources(SRC_DIR.resolve("EnclosingClass.java"), CLASSES_10_DIR, "--release", "10");
    }

    static void compileSources(Path sourceFile, Path dest, String... options) throws IOException {
        Stream<String> ops = Stream.of("-cp", Utils.TEST_CLASSES + File.pathSeparator + CLASSES_DIR);
        if (options != null && options.length > 0) {
            ops = Stream.concat(ops, Arrays.stream(options));
        }
        if (!CompilerUtils.compile(sourceFile, dest, ops.toArray(String[]::new))) {
            throw new RuntimeException("Compilation of the test failed: " + sourceFile);
        }
    }

    static Class<?> defineHiddenClass(String name) throws Exception {
        byte[] bytes = Files.readAllBytes(CLASSES_DIR.resolve(name + ".class"));
        Class<?> hc = lookup().defineHiddenClass(bytes, false).lookupClass();
        assertHiddenClass(hc);
        singletonNest(hc);
        return hc;
    }

    // basic test on a hidden class
    @Test
    public void hiddenClass() throws Throwable {
        HiddenTest t = (HiddenTest)defineHiddenClass("HiddenClass").newInstance();
        t.test();

        // sanity check
        Class<?> c = t.getClass();
        Class<?>[] intfs = c.getInterfaces();
        assertTrue(c.isHidden());
        assertFalse(c.isPrimitive());
        assertTrue(intfs.length == 1);
        assertTrue(intfs[0] == HiddenTest.class);
        assertTrue(c.getCanonicalName() == null);

        String hcName = "HiddenClass";
        String hcSuffix = "0x[0-9a-f]+";
        assertTrue(c.getName().matches(hcName + "/" + hcSuffix));
        assertTrue(c.descriptorString().matches("L" + hcName + "." + hcSuffix + ";"), c.descriptorString());

        // test array of hidden class
        testHiddenArray(c);

        // test setAccessible
        checkSetAccessible(c, "realTest");
        checkSetAccessible(c, "test");
    }

    // primitive class is not a hidden class
    @Test
    public void primitiveClass() {
        assertFalse(int.class.isHidden());
        assertFalse(String.class.isHidden());
    }

    private void testHiddenArray(Class<?> type) throws Exception {
        // array of hidden class
        Object array = Array.newInstance(type, 2);
        Class<?> arrayType = array.getClass();
        assertTrue(arrayType.isArray());
        assertTrue(Array.getLength(array) == 2);
        assertFalse(arrayType.isHidden());

        String hcName = "HiddenClass";
        String hcSuffix = "0x[0-9a-f]+";
        assertTrue(arrayType.getName().matches("\\[" + "L" + hcName + "/" + hcSuffix + ";"));
        assertTrue(arrayType.descriptorString().matches("\\[" + "L" + hcName + "." + hcSuffix + ";"));

        assertTrue(arrayType.getComponentType().isHidden());
        assertTrue(arrayType.getComponentType() == type);
        Object t = type.newInstance();
        Array.set(array, 0, t);
        Object o = Array.get(array, 0);
        assertTrue(o == t);
    }

    private void checkSetAccessible(Class<?> c, String name, Class<?>... ptypes) throws Exception {
        Method m = c.getDeclaredMethod(name, ptypes);
        assertTrue(m.trySetAccessible());
        m.setAccessible(true);
    }

    // Define a hidden class that uses lambda
    // This verifies LambdaMetaFactory supports the caller which is a hidden class
    @Test
    public void testLambda() throws Throwable {
        HiddenTest t = (HiddenTest)defineHiddenClass("Lambda").newInstance();
        try {
            t.test();
        } catch (Error e) {
            if (!e.getMessage().equals("thrown by " + t.getClass().getName())) {
                throw e;
            }
        }
    }

    // Define a hidden class that uses lambda and contains its implementation
    // This verifies LambdaMetaFactory supports the caller which is a hidden class
    @Test
    public void testHiddenLambda() throws Throwable {
        HiddenTest t = (HiddenTest)defineHiddenClass("HiddenLambda").newInstance();
        try {
            t.test();
        } catch (Error e) {
            if (!e.getMessage().equals("thrown by " + t.getClass().getName())) {
                throw e;
            }
        }
    }

    // Verify the nest host and nest members of a hidden class and hidden nestmate class
    @Test
    public void testHiddenNestHost() throws Throwable {
        byte[] hc1 = hiddenClassBytes;
        Lookup lookup1 = lookup().defineHiddenClass(hc1, false);
        Class<?> host = lookup1.lookupClass();

        byte[] hc2 = Files.readAllBytes(CLASSES_DIR.resolve("Lambda.class"));
        Lookup lookup2 = lookup1.defineHiddenClass(hc2, false, NESTMATE);
        Class<?> member = lookup2.lookupClass();

        // test nest membership and reflection API
        assertTrue(host.isNestmateOf(member));
        assertTrue(host.getNestHost() == host);
        // getNestHost and getNestMembers return the same value when calling
        // on a nest member and the nest host
        assertTrue(member.getNestHost() == host.getNestHost());
        assertTrue(Arrays.equals(member.getNestMembers(), host.getNestMembers()));
        // getNestMembers includes the nest host that can be a hidden class but
        // only includes static nest members
        assertTrue(host.getNestMembers().length == 1);
        assertTrue(host.getNestMembers()[0] == host);
    }

    @DataProvider(name = "hiddenClasses")
    private Object[][] hiddenClasses() {
        return new Object[][] {
                new Object[] { "HiddenInterface", false },
                new Object[] { "AbstractClass", false },
                // a hidden annotation is useless because it cannot be referenced by any class
                new Object[] { "HiddenAnnotation", false },
                // class file with bad NestHost, NestMembers and InnerClasses or EnclosingMethod attribute
                // define them as nestmate to verify Class::getNestHost and getNestMembers
                new Object[] { "Outer", true },
                new Object[] { "Outer$Inner", true },
                new Object[] { "EnclosingClass", true },
                new Object[] { "EnclosingClass$1", true },
        };
    }

    /*
     * Test that class file bytes that can be defined as a normal class
     * can be successfully created as a hidden class even it might not
     * make sense as a hidden class.  For example, a hidden annotation
     * is not useful as it cannot be referenced and an outer/inner class
     * when defined as a hidden effectively becomes a final top-level class.
     */
    @Test(dataProvider = "hiddenClasses")
    public void defineHiddenClass(String name, boolean nestmate) throws Exception {
        byte[] bytes = Files.readAllBytes(CLASSES_DIR.resolve(name + ".class"));
        Class<?> hc;
        Class<?> host;
        if (nestmate) {
            hc = lookup().defineHiddenClass(bytes, false, NESTMATE).lookupClass();
            host = lookup().lookupClass().getNestHost();
        } else {
            hc = lookup().defineHiddenClass(bytes, false).lookupClass();
            host = hc;
        }
        assertTrue(hc.getNestHost() == host);
        assertTrue(hc.getNestMembers().length == 1);
        assertTrue(hc.getNestMembers()[0] == host);
    }

    @DataProvider(name = "emptyClasses")
    private Object[][] emptyClasses() {
        return new Object[][] {
                new Object[] { "EmptyHiddenSynthetic", ACC_SYNTHETIC },
                new Object[] { "EmptyHiddenEnum", ACC_ENUM },
                new Object[] { "EmptyHiddenAbstractClass", ACC_ABSTRACT },
                new Object[] { "EmptyHiddenInterface", ACC_ABSTRACT|ACC_INTERFACE },
                new Object[] { "EmptyHiddenAnnotation", ACC_ANNOTATION|ACC_ABSTRACT|ACC_INTERFACE },
        };
    }

    /*
     * Test if an empty class with valid access flags can be created as a hidden class
     * as long as it does not violate the restriction of a hidden class.
     *
     * A meaningful enum type defines constants of that enum type.  So
     * enum class containing constants of its type should not be a hidden
     * class.
     */
    @Test(dataProvider = "emptyClasses")
    public void emptyHiddenClass(String name, int accessFlags) throws Exception {
        byte[] bytes = (accessFlags == ACC_ENUM) ? classBytes(name, CD_Enum, accessFlags)
                : classBytes(name, accessFlags);
        Class<?> hc = lookup().defineHiddenClass(bytes, false).lookupClass();
        switch (accessFlags) {
            case ACC_SYNTHETIC:
                assertTrue(hc.isSynthetic());
                assertFalse(hc.isEnum());
                assertFalse(hc.isAnnotation());
                assertFalse(hc.isInterface());
                break;
            case ACC_ENUM:
                assertFalse(hc.isSynthetic());
                assertTrue(hc.isEnum());
                assertFalse(hc.isAnnotation());
                assertFalse(hc.isInterface());
                break;
            case ACC_ABSTRACT:
                assertFalse(hc.isSynthetic());
                assertFalse(hc.isEnum());
                assertFalse(hc.isAnnotation());
                assertFalse(hc.isInterface());
                break;
            case ACC_ABSTRACT|ACC_INTERFACE:
                assertFalse(hc.isSynthetic());
                assertFalse(hc.isEnum());
                assertFalse(hc.isAnnotation());
                assertTrue(hc.isInterface());
                break;
            case ACC_ANNOTATION|ACC_ABSTRACT|ACC_INTERFACE:
                assertFalse(hc.isSynthetic());
                assertFalse(hc.isEnum());
                assertTrue(hc.isAnnotation());
                assertTrue(hc.isInterface());
                break;
            default:
                throw new IllegalArgumentException("unexpected access flag: " + accessFlags);
        }
        assertTrue(hc.isHidden());
        assertTrue(hc.getModifiers() == (ACC_PUBLIC|accessFlags));
        assertFalse(hc.isLocalClass());
        assertFalse(hc.isMemberClass());
        assertFalse(hc.isAnonymousClass());
        assertFalse(hc.isArray());
    }

    // These class files can't be defined as hidden classes
    @DataProvider(name = "cantBeHiddenClasses")
    private Object[][] cantBeHiddenClasses() {
        return new Object[][] {
                // a hidden class can't be a field's declaring type
                // enum class with static final HiddenEnum[] $VALUES:
                new Object[] { "HiddenEnum" },
                // supertype of this class is a hidden class
                new Object[] { "HiddenSuper" },
                // a record class whose equals(HiddenRecord, Object) method
                // refers to a hidden class in the parameter type and fails
                // verification.  Perhaps this method signature should be reconsidered.
                new Object[] { "HiddenRecord" },
        };
    }

    /*
     * These class files
     */
    @Test(dataProvider = "cantBeHiddenClasses", expectedExceptions = NoClassDefFoundError.class)
    public void failToDeriveAsHiddenClass(String name) throws Exception {
        byte[] bytes = Files.readAllBytes(CLASSES_DIR.resolve(name + ".class"));
        Class<?> hc = lookup().defineHiddenClass(bytes, false).lookupClass();
    }

    /*
     * A hidden class can be successfully created but fails to be reflected
     * if it refers to its own type in the descriptor.
     * e.g. Class::getMethods resolves the declaring type of fields,
     * parameter types and return type.
     */
    @Test
    public void hiddenCantReflect() throws Throwable {
        HiddenTest t = (HiddenTest)defineHiddenClass("HiddenCantReflect").newInstance();
        t.test();

        Class<?> c = t.getClass();
        Class<?>[] intfs = c.getInterfaces();
        assertTrue(intfs.length == 1);
        assertTrue(intfs[0] == HiddenTest.class);

        try {
            // this would cause loading of class HiddenCantReflect and NCDFE due
            // to error during verification
            c.getDeclaredMethods();
        } catch (NoClassDefFoundError e) {
            Throwable x = e.getCause();
            if (x == null || !(x instanceof ClassNotFoundException && x.getMessage().contains("HiddenCantReflect"))) {
                throw e;
            }
        }
    }

    @Test(expectedExceptions = { IllegalArgumentException.class })
    public void cantDefineModule() throws Throwable {
        Path src = Paths.get("module-info.java");
        Path dir = CLASSES_DIR.resolve("m");
        Files.write(src, List.of("module m {}"), StandardCharsets.UTF_8);
        compileSources(src, dir);

        byte[] bytes = Files.readAllBytes(dir.resolve("module-info.class"));
        lookup().defineHiddenClass(bytes, false);
    }

    @Test(expectedExceptions = { IllegalArgumentException.class })
    public void cantDefineClassInAnotherPackage() throws Throwable {
        Path src = Paths.get("ClassInAnotherPackage.java");
        Files.write(src, List.of("package p;", "public class ClassInAnotherPackage {}"), StandardCharsets.UTF_8);
        compileSources(src, CLASSES_DIR);

        byte[] bytes = Files.readAllBytes(CLASSES_DIR.resolve("p").resolve("ClassInAnotherPackage.class"));
        lookup().defineHiddenClass(bytes, false);
    }

    @Test(expectedExceptions = { IllegalAccessException.class })
    public void lessPrivilegedLookup() throws Throwable {
        Lookup lookup = lookup().dropLookupMode(Lookup.PRIVATE);
        lookup.defineHiddenClass(hiddenClassBytes, false);
    }

    @Test(expectedExceptions = { UnsupportedClassVersionError.class })
    public void badClassFileVersion() throws Throwable {
        Path dir = Paths.get(System.getProperty("test.classes", "."));
        byte[] bytes = Files.readAllBytes(dir.resolve("BadClassFileVersion.class"));
        lookup().defineHiddenClass(bytes, false);
    }

    // malformed class files
    @DataProvider(name = "malformedClassFiles")
    private Object[][] malformedClassFiles() throws IOException {
        Path dir = Paths.get(System.getProperty("test.classes", "."));
        return new Object[][] {
                // `this_class` has invalid CP entry
                new Object[] { Files.readAllBytes(dir.resolve("BadClassFile.class")) },
                new Object[] { Files.readAllBytes(dir.resolve("BadClassFile2.class")) },
                // truncated file
                new Object[] { new byte[0] },
                new Object[] { new byte[] {(byte) 0xCA, (byte) 0xBA, (byte) 0xBE, (byte) 0x00} },
        };
    }

    @Test(dataProvider = "malformedClassFiles", expectedExceptions = ClassFormatError.class)
    public void badClassFile(byte[] bytes) throws Throwable {
        lookup().defineHiddenClass(bytes, false);
    }

    @DataProvider(name = "nestedTypesOrAnonymousClass")
    private Object[][] nestedTypesOrAnonymousClass() {
        return new Object[][] {
                // class file with bad InnerClasses or EnclosingMethod attribute
                new Object[] { "Outer", null },
                new Object[] { "Outer$Inner", "Outer" },
                new Object[] { "EnclosingClass", null },
                new Object[] { "EnclosingClass$1", "EnclosingClass" },
        };
    }

    @Test(dataProvider = "nestedTypesOrAnonymousClass")
    public void hasInnerClassesOrEnclosingMethodAttribute(String className, String badDeclaringClassName) throws Throwable {
        byte[] bytes = Files.readAllBytes(CLASSES_10_DIR.resolve(className + ".class"));
        Class<?> hc = lookup().defineHiddenClass(bytes, false).lookupClass();
        hiddenClassWithBadAttribute(hc, badDeclaringClassName);
    }

    // define a hidden class with static nest membership
    @Test
    public void hasStaticNestHost() throws Exception {
        byte[] bytes = Files.readAllBytes(CLASSES_DIR.resolve("Outer$Inner.class"));
        Class<?> hc = lookup().defineHiddenClass(bytes, false).lookupClass();
        hiddenClassWithBadAttribute(hc, "Outer");
    }

    @Test
    public void hasStaticNestMembers() throws Throwable {
        byte[] bytes = Files.readAllBytes(CLASSES_DIR.resolve("Outer.class"));
        Class<?> hc = lookup().defineHiddenClass(bytes, false).lookupClass();
        assertHiddenClass(hc);
        assertTrue(hc.getNestHost() == hc);
        Class<?>[] members = hc.getNestMembers();
        assertTrue(members.length == 1 && members[0] == hc);
    }

    // a hidden class with bad InnerClasses or EnclosingMethod attribute
    private void hiddenClassWithBadAttribute(Class<?> hc, String badDeclaringClassName) {
        assertTrue(hc.isHidden());
        assertTrue(hc.getCanonicalName() == null);
        assertTrue(hc.getName().contains("/"));

        if (badDeclaringClassName == null) {
            // the following reflection API assumes a good name in InnerClasses
            // or EnclosingMethod attribute can successfully be resolved.
            assertTrue(hc.getSimpleName().length() > 0);
            assertFalse(hc.isAnonymousClass());
            assertFalse(hc.isLocalClass());
            assertFalse(hc.isMemberClass());
        } else {
            declaringClassNotFound(hc, badDeclaringClassName);
        }

        // validation of nest membership
        assertTrue(hc.getNestHost() == hc);
        // validate the static nest membership
        Class<?>[] members = hc.getNestMembers();
        assertTrue(members.length == 1 && members[0] == hc);
    }

    // Class::getSimpleName, Class::isMemberClass
    private void declaringClassNotFound(Class<?> c, String cn) {
        try {
            // fail to find declaring/enclosing class
            c.isMemberClass();
            assertTrue(false);
        } catch (NoClassDefFoundError e) {
            if (!e.getMessage().equals(cn)) {
                throw e;
            }
        }
        try {
            // fail to find declaring/enclosing class
            c.getSimpleName();
            assertTrue(false);
        } catch (NoClassDefFoundError e) {
            if (!e.getMessage().equals(cn)) {
                throw e;
            }
        }
    }

    private static void singletonNest(Class<?> hc) {
        assertTrue(hc.getNestHost() == hc);
        assertTrue(hc.getNestMembers().length == 1);
        assertTrue(hc.getNestMembers()[0] == hc);
    }

    private static void assertHiddenClass(Class<?> hc) {
        assertTrue(hc.isHidden());
        assertTrue(hc.getCanonicalName() == null);
        assertTrue(hc.getName().contains("/"));
        assertFalse(hc.isAnonymousClass());
        assertFalse(hc.isLocalClass());
        assertFalse(hc.isMemberClass());
        assertFalse(hc.getSimpleName().isEmpty()); // sanity check
    }

    private static byte[] classBytes(String classname, int accessFlags) {
        return classBytes(classname, CD_Object, accessFlags);
    }

    private static byte[] classBytes(String classname, ClassDesc superType, int accessFlags) {
        return ClassFile.of().build(ClassDesc.ofInternalName(classname), clb -> clb
                .withVersion(JAVA_14_VERSION, 0)
                .withFlags(accessFlags | ACC_PUBLIC)
                .withSuperclass(superType));
    }
}
