/*
 * Copyright (c) 2013, 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 8027232
 * @library /test/lib/
 * @modules jdk.zipfs
 * @compile LambdaAsm.java
 * @run main/othervm LambdaAsm
 * @summary ensures that j.l.i.InvokerByteCodeGenerator and Class-File API
 * generate bytecodes with correct constant pool references
 */
import java.io.IOException;
import java.lang.classfile.Attributes;
import java.lang.classfile.ClassFile;
import java.lang.classfile.ClassModel;
import java.lang.classfile.Opcode;
import java.lang.classfile.attribute.CodeAttribute;
import java.lang.classfile.constantpool.ConstantPool;
import java.lang.classfile.constantpool.MethodRefEntry;
import java.lang.classfile.instruction.InvokeInstruction;
import java.lang.constant.ClassDesc;
import java.lang.constant.MethodTypeDesc;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.util.ArrayList;
import java.nio.file.DirectoryStream;
import java.nio.file.Path;
import jdk.test.lib.compiler.CompilerUtils;
import jdk.test.lib.process.OutputAnalyzer;

import static java.lang.constant.ConstantDescs.*;
import static java.lang.classfile.ClassFile.*;
import static java.nio.file.Files.*;
import static jdk.test.lib.process.ProcessTools.*;

public class LambdaAsm {
    static final Path DUMP_LAMBDA_PROXY_CLASS_FILES = Path.of("DUMP_LAMBDA_PROXY_CLASS_FILES");
    static final Path SRC = Path.of("src");
    static final Path CLASSES = Path.of("classes");

    static void init() throws Exception {
        emitCode();
        CompilerUtils.compile(SRC, CLASSES);
        OutputAnalyzer outputAnalyzer = executeProcess(createTestJavaProcessBuilder(
                "-Djdk.invoke.LambdaMetafactory.dumpProxyClassFiles=true",
                "-cp", CLASSES.toString(), "A"));
        outputAnalyzer.shouldHaveExitValue(0);
    }

    static void emitCode() throws IOException {
        ArrayList<String> scratch = new ArrayList<>();
        scratch.add("import java.util.function.*;");
        scratch.add("class A {");
        scratch.add("   interface I {");
        scratch.add("       default Supplier<Integer> a() { return () -> 1; }");
        scratch.add("       default Supplier<Integer> b(int i) { return () -> i; }");
        scratch.add("       default Supplier<Integer> c(int i) { return () -> m(i); }");
        scratch.add("       int m(int i);");
        scratch.add("       static Integer d() { return 0; }");
        scratch.add("   }");
        scratch.add("   static class C implements I {");
        scratch.add("       public int m(int i) { return i;}");
        scratch.add("   }");
        scratch.add("   public static void main(String[] args) {");
        scratch.add("       I i = new C();");
        scratch.add("       i.a();");
        scratch.add("       i.b(1);");
        scratch.add("       i.c(1);");
        scratch.add("       I.d();");
        scratch.add("   }");
        scratch.add("}");

        Path testFile = SRC.resolve("A.java");
        Files.createDirectories(SRC);
        Files.write(testFile, scratch, Charset.defaultCharset());
    }

    static void checkMethod(String cname, String mname, ConstantPool cp,
            CodeAttribute code) throws IllegalArgumentException {
        for (var inst : code) {
            if (inst instanceof InvokeInstruction inv && (inv.opcode() == Opcode.INVOKESPECIAL
                    || inv.opcode() == Opcode.INVOKEINTERFACE)) {
                var ref = inv.method();
                System.out.println("Verifying " + cname + ":" + mname +
                        " instruction:" + inv.opcode() + " index @" + ref.index());
                if (ref instanceof MethodRefEntry) {
                    throw new RuntimeException("unexpected CP type expected "
                            + "InterfaceMethodRef, got MethodRef, " + cname
                            + ", " + mname);
                }
            }
        }
    }

    static int checkMethod(ClassModel cf, String mthd) throws Exception {
        if (cf.majorVersion() < 52) {
            throw new RuntimeException("unexpected class file version, in "
                    + cf.thisClass().asInternalName() + "expected 52, got "
                    + cf.majorVersion());
        }
        int count = 0;
        for (var m : cf.methods()) {
            String mname = m.methodName().stringValue();
            if (mname.equals(mthd)) {
                for (var a : m.findAttributes(Attributes.code())) {
                    count++;
                    checkMethod(cf.thisClass().asInternalName(), mname,
                            cf.constantPool(), a);
                }
            }
        }
        return count;
    }

    static void verifyInvokerBytecodeGenerator() throws Exception {
        int count = 0;
        int mcount = 0;
        try (DirectoryStream<Path> ds = newDirectoryStream(DUMP_LAMBDA_PROXY_CLASS_FILES,
                // filter in lambda proxy classes
                "A$I$$Lambda.*.class")) {
            for (Path p : ds) {
                System.out.println(p.toFile());
                ClassModel cm = ClassFile.of().parse(p);
                // Check those methods implementing Supplier.get
                mcount += checkMethod(cm, "get");
                count++;
            }
        }
        if (count < 3) {
            throw new RuntimeException("unexpected number of files, "
                    + "expected atleast 3 files, but got only " + count);
        }
        if (mcount < 3) {
            throw new RuntimeException("unexpected number of methods, "
                    + "expected atleast 3 methods, but got only " + mcount);
        }
    }

    static void verifyASM() throws Exception {
        var functionDesc = ClassDesc.ofInternalName("java/util/function/Function");
        byte[] carray = ClassFile.of().build(ClassDesc.of("X"), clb -> clb
                .withVersion(JAVA_8_VERSION, 0)
                .withFlags(ACC_PUBLIC)
                .withSuperclass(CD_Object)
                .withMethodBody("foo", MTD_void, ACC_STATIC, cob -> cob
                        .invokestatic(functionDesc, "identity", MethodTypeDesc.of(functionDesc), true)
                )
        );
        // for debugging
        // write((new File("X.class")).toPath(), carray, CREATE, TRUNCATE_EXISTING);

        // verify using javap/classfile reader
        ClassModel cm = ClassFile.of().parse(carray);
        int mcount = checkMethod(cm, "foo");
        if (mcount < 1) {
            throw new RuntimeException("unexpected method count, expected 1" +
                    "but got " + mcount);
        }
    }

    public static void main(String... args) throws Exception {
        init();
        verifyInvokerBytecodeGenerator();
        verifyASM();
    }
}
