hotspot/test/compiler/jvmci/compilerToVM/ResolveMethodTest.java
changeset 33160 c59f1676d27e
child 33730 30e064828045
child 33632 038347770a9e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/compilerToVM/ResolveMethodTest.java	Thu Oct 08 12:49:30 2015 -1000
@@ -0,0 +1,175 @@
+/*
+ * 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 8136421
+ * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64"
+ * @library / /testlibrary /../../test/lib
+ * @compile ../common/CompilerToVMHelper.java
+ * @build compiler.jvmci.compilerToVM.ResolveMethodTest
+ * @run main ClassFileInstaller
+ *      jdk.vm.ci.hotspot.CompilerToVMHelper
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockExperimentalVMOptions
+ *     -XX:+EnableJVMCI compiler.jvmci.compilerToVM.ResolveMethodTest
+ */
+
+package compiler.jvmci.compilerToVM;
+
+import compiler.jvmci.common.testcases.AbstractClass;
+import compiler.jvmci.common.testcases.AbstractClassExtender;
+import compiler.jvmci.common.testcases.MultipleImplementer1;
+import compiler.jvmci.common.testcases.MultipleImplementer2;
+import compiler.jvmci.common.testcases.MultipleImplementersInterface;
+import compiler.jvmci.common.testcases.SingleImplementer;
+import compiler.jvmci.common.testcases.SingleImplementerInterface;
+import compiler.jvmci.common.testcases.SingleSubclass;
+import compiler.jvmci.common.testcases.SingleSubclassedClass;
+import compiler.jvmci.common.CTVMUtilities;
+import java.util.HashSet;
+import java.util.Set;
+import jdk.vm.ci.hotspot.CompilerToVMHelper;
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl;
+import jdk.vm.ci.hotspot.HotSpotResolvedObjectTypeImpl;
+import jdk.test.lib.Asserts;
+import jdk.test.lib.Utils;
+import sun.misc.Unsafe;
+
+public class ResolveMethodTest {
+    private static final Unsafe UNSAFE = Utils.getUnsafe();
+
+    public static void main(String args[]) {
+        ResolveMethodTest test = new ResolveMethodTest();
+        // positive cases
+        try {
+            for (TestCase tcase: createTestCases()) {
+                test.runTest(tcase);
+            }
+        } catch (NoSuchMethodException e) {
+            throw new Error("TEST BUG: can't find requested method", e);
+        }
+    }
+
+    private static Set<TestCase> createTestCases() {
+        Set<TestCase> result = new HashSet<>();
+        // a usual class public method
+        result.add(new TestCase(SingleSubclass.class, SingleSubclass.class,
+                "usualMethod", ResolveMethodTest.class, true));
+        // an array method
+        result.add(new TestCase(int[].class, Object.class, "toString",
+                ResolveMethodTest.class, true));
+        // a method from base class, which was overriden in tested one
+        result.add(new TestCase(SingleSubclass.class, SingleSubclass.class,
+                "overridenMethod", ResolveMethodTest.class, true));
+        // a method from base class, which was not overriden in tested one
+        result.add(new TestCase(SingleSubclass.class,
+                SingleSubclassedClass.class, "inheritedMethod",
+                ResolveMethodTest.class, true));
+        /* a method from base class, which was overriden in tested one with
+           base class as holder */
+        result.add(new TestCase(SingleSubclass.class,
+                SingleSubclassedClass.class, "overridenMethod",
+                ResolveMethodTest.class, true));
+        // an interface method
+        result.add(new TestCase(SingleImplementer.class,
+                SingleImplementerInterface.class, "interfaceMethod",
+                ResolveMethodTest.class, true));
+        // an interface default method overriden in implementer
+        result.add(new TestCase(MultipleImplementer1.class,
+                MultipleImplementersInterface.class, "defaultMethod",
+                ResolveMethodTest.class, true));
+        // an interface default method not overriden in implementer
+        result.add(new TestCase(MultipleImplementer2.class,
+                MultipleImplementersInterface.class, "defaultMethod",
+                ResolveMethodTest.class, true));
+        // an abstract method
+        result.add(new TestCase(AbstractClassExtender.class, AbstractClass.class,
+                "abstractMethod", ResolveMethodTest.class, true));
+        // private method with right accessor
+        result.add(new TestCase(SingleSubclass.class, SingleSubclass.class,
+                "privateMethod", SingleSubclass.class, true));
+        // package-private method with right accessor
+        result.add(new TestCase(SingleSubclass.class, SingleSubclass.class,
+                "defaultAccessMethod", SingleSubclass.class, true));
+
+        // negative cases
+
+        // private method of another class
+        result.add(new TestCase(SingleSubclass.class, SingleSubclass.class,
+                "privateMethod", ResolveMethodTest.class, false));
+        // package-private method from another package
+        result.add(new TestCase(SingleSubclass.class, SingleSubclass.class,
+                "defaultAccessMethod", ResolveMethodTest.class, false));
+        return result;
+    }
+
+    private void runTest(TestCase tcase) throws NoSuchMethodException {
+        System.out.println(tcase);
+        HotSpotResolvedJavaMethodImpl metaspaceMethod = CTVMUtilities
+                .getResolvedMethod(tcase.holder,
+                        tcase.holder.getDeclaredMethod(tcase.methodName));
+        HotSpotResolvedObjectTypeImpl holderMetaspace = CompilerToVMHelper
+                .lookupType(Utils.toJVMTypeSignature(tcase.holder),
+                        getClass(), /* resolve = */ true);
+        HotSpotResolvedObjectTypeImpl callerMetaspace = CompilerToVMHelper
+                .lookupType(Utils.toJVMTypeSignature(tcase.caller),
+                        getClass(), /* resolve = */ true);
+        HotSpotResolvedJavaMethodImpl resolvedMetaspaceMethod
+                = CompilerToVMHelper.resolveMethod(holderMetaspace,
+                        metaspaceMethod, callerMetaspace);
+        if (tcase.isPositive) {
+            Asserts.assertNotNull(resolvedMetaspaceMethod,
+                    "Unexpected null resolved method value for "
+                            + tcase.methodName);
+            Asserts.assertEQ(metaspaceMethod.getName(), tcase.methodName,
+                    "Reflection and c2vm method names doesn't match");
+        } else {
+            Asserts.assertNull(resolvedMetaspaceMethod,
+                    "Method unexpectedly resolved");
+        }
+    }
+
+    private static class TestCase {
+        public final Class<?> receiver;
+        public final Class<?> holder;
+        public final Class<?> caller;
+        public final String methodName;
+        public final boolean isPositive;
+
+        public TestCase(Class<?> recv, Class<?> holder, String methodName,
+                Class<?> caller, boolean isPositive) {
+            this.receiver = recv;
+            this.holder = holder;
+            this.caller = caller;
+            this.methodName = methodName;
+            this.isPositive = isPositive;
+        }
+
+        @Override
+        public String toString() {
+            return String.format("CASE: receiver=%s, holder=%s, method=%s,"
+                + "caller=%s, isPositive=%s%n", receiver.getName(),
+                holder.getName(), methodName, caller.getName(), isPositive);
+        }
+    }
+}