/*
 * Copyright (c) 2015, 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 8140450 8152893 8189291 8210375
 * @summary Basic test for StackWalker.getCallerClass()
 * @run main/othervm GetCallerClassTest
 * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+ShowHiddenFrames GetCallerClassTest
 */

import static java.lang.StackWalker.Option.*;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.List;

public class GetCallerClassTest {
    private final StackWalker walker;
    private final boolean expectUOE;

    public GetCallerClassTest(StackWalker sw, boolean expect) {
        this.walker = sw;
        this.expectUOE = expect;
    }
    public static void main(String... args) throws Exception {
        new GetCallerClassTest(StackWalker.getInstance(), true).test();
        new GetCallerClassTest(StackWalker.getInstance(RETAIN_CLASS_REFERENCE), false).test();
        new GetCallerClassTest(StackWalker.getInstance(EnumSet.of(RETAIN_CLASS_REFERENCE,
                                                                  SHOW_HIDDEN_FRAMES)), false).test();
    }

    public void test() {
        new TopLevelCaller().run();
        new LambdaTest().run();
        new Nested().createNestedCaller().run();
        new InnerClassCaller().run();
        new ReflectionTest().run();

        List<Thread> threads = Arrays.asList(
                new Thread(new TopLevelCaller()),
                new Thread(new LambdaTest()),
                new Thread(new Nested().createNestedCaller()),
                new Thread(new InnerClassCaller()),
                new Thread(new ReflectionTest())
        );
        threads.stream().forEach(Thread::start);
        threads.stream().forEach(t -> {
            try {
                t.join();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });
    }

    public static void staticGetCallerClass(StackWalker stackWalker,
                                            Class<?> expected,
                                            boolean expectUOE) {
        try {
            Class<?> c = stackWalker.getCallerClass();
            assertEquals(c, expected);
            if (expectUOE) { // Should have thrown
                throw new RuntimeException("Didn't get expected exception");
            }
        } catch (RuntimeException e) { // also catches UOE
            if (expectUOE && causeIsUOE(e)) {
                return; /* expected */
            }
            System.err.println("Unexpected exception:");
            throw e;
        }
    }

    public static void reflectiveGetCallerClass(StackWalker stackWalker,
                                                Class<?> expected,
                                                boolean expectUOE) {
        try {
            // Use reflection to call Method::invoke that invokes StackWalker::getCallerClass
            Method m = StackWalker.class.getMethod("getCallerClass");
            Method invoke = Method.class.getMethod("invoke", Object.class, Object[].class);
            Class<?> c = (Class<?>) invoke.invoke(m, new Object[] { stackWalker, null });
            assertEquals(c, expected);
            if (expectUOE) { // Should have thrown
                throw new RuntimeException("Didn't get expected exception");
            }
        } catch (Throwable e) {
            if (expectUOE && causeIsUOE(e)) {
                return; /* expected */
            }
            System.err.println("Unexpected exception:");
            throw new RuntimeException(e);
        }
    }

    public static void methodHandleGetCallerClass(StackWalker stackWalker,
                                                  Class<?> expected,
                                                  boolean expectUOE) {
        MethodHandles.Lookup lookup = MethodHandles.lookup();
        try {
            MethodHandle mh = lookup.findVirtual(StackWalker.class, "getCallerClass",
                                                 MethodType.methodType(Class.class));
            Class<?> c = (Class<?>) mh.invokeExact(stackWalker);
            assertEquals(c, expected);
            if (expectUOE) { // Should have thrown
                throw new RuntimeException("Didn't get expected exception");
            }
        } catch (Throwable e) {
            if (expectUOE && causeIsUOE(e)) {
                return; /* expected */
            }
            System.err.println("Unexpected exception:");
            throw new RuntimeException(e);
        }
    }

    public static void assertEquals(Class<?> c, Class<?> expected) {
        if (expected != c) {
            throw new RuntimeException("Got " + c + ", but expected " + expected);
        }
    }

    /** Is there an UnsupportedOperationException in there? */
    public static boolean causeIsUOE(Throwable t) {
        while (t != null) {
            if (t instanceof UnsupportedOperationException) {
                return true;
            }
            t = t.getCause();
        }
        return false;
    }

    class TopLevelCaller implements Runnable {
        public void run() {
            GetCallerClassTest.staticGetCallerClass(walker, this.getClass(), expectUOE);
            GetCallerClassTest.reflectiveGetCallerClass(walker, this.getClass(), expectUOE);
            GetCallerClassTest.methodHandleGetCallerClass(walker, this.getClass(), expectUOE);
        }
    }

    class LambdaTest implements Runnable {
        public void run() {
            Runnable lambdaRunnable = () -> {
                try {
                    Class<?> c = walker.getCallerClass();

                    assertEquals(c, LambdaTest.class);
                    if (expectUOE) { // Should have thrown
                        throw new RuntimeException("Didn't get expected exception");
                    }
                } catch (Throwable e) {
                    if (expectUOE && causeIsUOE(e)) {
                        return; /* expected */
                    }
                    System.err.println("Unexpected exception:");
                    throw new RuntimeException(e);
                }
            };
            lambdaRunnable.run();
        }
    }

    class Nested {
        NestedClassCaller createNestedCaller() { return new NestedClassCaller(); }
        class NestedClassCaller implements Runnable {
            public void run() {
                GetCallerClassTest.staticGetCallerClass(walker, this.getClass(), expectUOE);
                GetCallerClassTest.reflectiveGetCallerClass(walker, this.getClass(), expectUOE);
                GetCallerClassTest.methodHandleGetCallerClass(walker, this.getClass(), expectUOE);
            }
        }
    }

    class InnerClassCaller implements Runnable {
        public void run() {
            new Inner().test();
        }
        class Inner {
            void test() {
                GetCallerClassTest.staticGetCallerClass(walker, this.getClass(), expectUOE);
                GetCallerClassTest.reflectiveGetCallerClass(walker, this.getClass(), expectUOE);
                GetCallerClassTest.methodHandleGetCallerClass(walker, this.getClass(), expectUOE);
            }
        }
    }

    class ReflectionTest implements Runnable {
        final MethodType methodType =
            MethodType.methodType(void.class, StackWalker.class, Class.class, boolean.class);

        public void run() {
            callMethodHandle();
            callMethodHandleRefl();
            callMethodInvoke();
            callMethodInvokeRefl();
        }
        void callMethodHandle() {
            MethodHandles.Lookup lookup = MethodHandles.publicLookup();
            try {
                MethodHandle mh = lookup.findStatic(GetCallerClassTest.class,
                                                    "staticGetCallerClass",
                                                    methodType);
                mh.invokeExact(walker, ReflectionTest.class, expectUOE);
            } catch (Throwable e) {
                throw new RuntimeException(e);
            }
        }
        void callMethodHandleRefl() {
            MethodHandles.Lookup lookup = MethodHandles.publicLookup();
            try {
                MethodHandle mh = lookup.findStatic(GetCallerClassTest.class,
                                                    "reflectiveGetCallerClass",
                                                    methodType);
                mh.invokeExact(walker, ReflectionTest.class, expectUOE);
            } catch (Throwable e) {
                throw new RuntimeException(e);
            }
        }
        void callMethodInvoke() {
            try {
                Method m = GetCallerClassTest.class.getMethod("staticGetCallerClass",
                               StackWalker.class, Class.class, boolean.class);
                m.invoke(null, walker, ReflectionTest.class, expectUOE);
            } catch (NoSuchMethodException|IllegalAccessException|InvocationTargetException e) {
                throw new RuntimeException(e);
            }
        }
        void callMethodInvokeRefl() {
            try {
                Method m = GetCallerClassTest.class.getMethod("reflectiveGetCallerClass",
                               StackWalker.class, Class.class, boolean.class);
                m.invoke(null, walker, ReflectionTest.class, expectUOE);
            } catch (UnsupportedOperationException e) {
                throw e;
            } catch (NoSuchMethodException|IllegalAccessException|InvocationTargetException e) {
                throw new RuntimeException(e);
            }
        }
    }
}
