/*
 * Copyright (c) 2015, 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 8025636
 * @summary Synthetic frames should be hidden in exceptions
 * @compile -XDignore.symbol.file LUtils.java LambdaStackTrace.java
 * @run main LambdaStackTrace
 */

import jdk.internal.org.objectweb.asm.ClassWriter;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;

import static jdk.internal.org.objectweb.asm.Opcodes.ACC_ABSTRACT;
import static jdk.internal.org.objectweb.asm.Opcodes.ACC_INTERFACE;
import static jdk.internal.org.objectweb.asm.Opcodes.ACC_PUBLIC;
import static jdk.internal.org.objectweb.asm.Opcodes.V1_7;

public class LambdaStackTrace {

    static File classes = new File(System.getProperty("test.classes"));

    public static void main(String[] args) throws Exception {
        testBasic();
        testBridgeMethods();
    }

    /**
     * Test the simple case
     */
    private static void testBasic() throws Exception {
        try {
            Runnable r = () -> {
                throw new RuntimeException();
            };
            r.run();
        } catch (Exception ex) {
            // Before 8025636 the stacktrace would look like:
            //  at LambdaStackTrace.lambda$main$0(LambdaStackTrace.java:37)
            //  at LambdaStackTrace$$Lambda$1/1937396743.run(<Unknown>:1000000)
            //  at LambdaStackTrace.testBasic(LambdaStackTrace.java:40)
            //  at ...
            //
            // We are verifying that the middle frame above is gone.

            verifyFrames(ex.getStackTrace(),
                    "LambdaStackTrace\\..*",
                    "LambdaStackTrace.testBasic");
        }
    }

    /**
     * Test the more complicated case with bridge methods.
     *
     * We set up the following interfaces:
     *
     * interface Maker {
     *   Object make();
     * }
     * interface StringMaker extends Maker {
     *   String make();
     * }
     *
     * And we will use them like so:
     *
     * StringMaker sm = () -> { throw new RuntimeException(); };
     * sm.make();
     * ((Maker)m).make();
     *
     * The first call is a "normal" interface call, the second will use a
     * bridge method. In both cases the generated lambda frame should
     * be removed from the stack trace.
     */
    private static void testBridgeMethods() throws Exception {
        // setup
        generateInterfaces();
        compileCaller();

        // test
        StackTraceElement[] frames = call("Caller", "callStringMaker");
        verifyFrames(frames,
                "Caller\\..*",
                "Caller.callStringMaker");

        frames = call("Caller", "callMaker");
        verifyFrames(frames,
                "Caller\\..*",
                "Caller.callMaker");
    }

    private static void generateInterfaces() throws IOException {
        // We can't let javac compile these interfaces because in > 1.8 it will insert
        // bridge methods into the interfaces - we want code that looks like <= 1.7,
        // so we generate it.
        try (FileOutputStream fw = new FileOutputStream(new File(classes, "Maker.class"))) {
            fw.write(generateMaker());
        }
        try (FileOutputStream fw = new FileOutputStream(new File(classes, "StringMaker.class"))) {
            fw.write(generateStringMaker());
        }
    }

    private static byte[] generateMaker() {
        // interface Maker {
        //   Object make();
        // }
        ClassWriter cw = new ClassWriter(0);
        cw.visit(V1_7, ACC_INTERFACE | ACC_ABSTRACT, "Maker", null, "java/lang/Object", null);
        cw.visitMethod(ACC_PUBLIC | ACC_ABSTRACT, "make",
                "()Ljava/lang/Object;", null, null);
        cw.visitEnd();
        return cw.toByteArray();
    }

    private static byte[] generateStringMaker() {
        // interface StringMaker extends Maker {
        //   String make();
        // }
        ClassWriter cw = new ClassWriter(0);
        cw.visit(V1_7, ACC_INTERFACE | ACC_ABSTRACT, "StringMaker", null, "java/lang/Object", new String[]{"Maker"});
        cw.visitMethod(ACC_PUBLIC | ACC_ABSTRACT, "make",
                "()Ljava/lang/String;", null, null);
        cw.visitEnd();
        return cw.toByteArray();
    }


    static void emitCode(File f) {
        ArrayList<String> scratch = new ArrayList<>();
        scratch.add("public class Caller {");
        scratch.add("    public static void callStringMaker() {");
        scratch.add("        StringMaker sm = () -> { throw new RuntimeException(); };");
        scratch.add("        sm.make();");
        scratch.add("    }");
        scratch.add("    public static void callMaker() {");
        scratch.add("        StringMaker sm = () -> { throw new RuntimeException(); };");
        scratch.add("        ((Maker) sm).make();");  // <-- This will call the bridge method
        scratch.add("    }");
        scratch.add("}");
        LUtils.createFile(f, scratch);
    }

    static void compileCaller() {
        File caller = new File(classes, "Caller.java");
        emitCode(caller);
        LUtils.compile("-cp", classes.getAbsolutePath(), "-d", classes.getAbsolutePath(), caller.getAbsolutePath());
    }

    private static void verifyFrames(StackTraceElement[] stack, String... patterns) throws Exception {
        for (int i = 0; i < patterns.length; i++) {
            String cm = stack[i].getClassName() + "." + stack[i].getMethodName();
            if (!cm.matches(patterns[i])) {
                System.err.println("Actual trace did not match expected trace at frame " + i);
                System.err.println("Expected frame patterns:");
                for (int j = 0; j < patterns.length; j++) {
                    System.err.println("  " + j + ": " + patterns[j]);
                }
                System.err.println("Actual frames:");
                for (int j = 0; j < patterns.length; j++) {
                    System.err.println("  " + j + ": " + stack[j]);
                }
                throw new Exception("Incorrect stack frames found");
            }
        }
    }

    private static StackTraceElement[] call(String clazz, String method) throws Exception {
        Class<?> c = Class.forName(clazz);
        try {
            Method m = c.getDeclaredMethod(method);
            m.invoke(null);
        } catch(InvocationTargetException ex) {
            return ex.getTargetException().getStackTrace();
        }
        throw new Exception("Expected exception to be thrown");
    }
}
