1 /*
2  * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.
8  *
9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  */
23 
24 /*
25  * @test
26  * @bug 8136421
27  * @requires vm.jvmci
28  * @library / /test/lib/
29  * @library ../common/patches
30  * @modules java.base/jdk.internal.misc
31  * @modules jdk.internal.vm.ci/jdk.vm.ci.hotspot
32  * @build jdk.internal.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
33  * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
34  *                   -XX:-UseJVMCICompiler
35  *                   compiler.jvmci.compilerToVM.GetImplementorTest
36  */
37 
38 package compiler.jvmci.compilerToVM;
39 
40 import compiler.jvmci.common.testcases.AbstractClass;
41 import compiler.jvmci.common.testcases.AbstractClassExtender;
42 import compiler.jvmci.common.testcases.DoNotExtendClass;
43 import compiler.jvmci.common.testcases.DoNotImplementInterface;
44 import compiler.jvmci.common.testcases.MultipleImplementer1;
45 import compiler.jvmci.common.testcases.MultipleImplementer2;
46 import compiler.jvmci.common.testcases.MultipleImplementersInterface;
47 import compiler.jvmci.common.testcases.SingleImplementer;
48 import compiler.jvmci.common.testcases.SingleImplementerInterface;
49 import compiler.jvmci.common.testcases.SingleSubclass;
50 import compiler.jvmci.common.testcases.SingleSubclassedClass;
51 import jdk.test.lib.Asserts;
52 import jdk.test.lib.Utils;
53 import jdk.vm.ci.hotspot.CompilerToVMHelper;
54 import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
55 
56 import java.util.HashSet;
57 import java.util.Set;
58 import java.util.stream.Stream;
59 
60 public class GetImplementorTest {
main(String args[])61     public static void main(String args[]) {
62         GetImplementorTest test = new GetImplementorTest();
63         for (TestCase tcase : createTestCases()) {
64             test.runTest(tcase);
65         }
66     }
67 
createTestCases()68     private static Set<TestCase> createTestCases() {
69         Set<TestCase> result = new HashSet<>();
70         Stream.of(
71                     SingleSubclass.class,
72                     AbstractClassExtender.class,
73                     MultipleImplementer2.class,
74                     MultipleImplementer1.class,
75                     MultipleImplementersInterface.class,
76                     DoNotImplementInterface.class,
77                     DoNotExtendClass.class,
78                     AbstractClass.class,
79                     SingleSubclassedClass.class)
80                 .forEach(Utils::ensureClassIsLoaded);
81         // an interface with single class implementing it
82         result.add(new TestCase(SingleImplementerInterface.class,
83                 SingleImplementer.class));
84         /* an interface with multiple implementers. According to getImplementor
85            javadoc, an itself should be returned in case of more than one
86            implementor
87          */
88         result.add(new TestCase(MultipleImplementersInterface.class,
89                 MultipleImplementersInterface.class));
90         // an interface with no implementors
91         result.add(new TestCase(DoNotImplementInterface.class, null));
92         // an abstract class with extender class
93         result.add(new TestCase(AbstractClass.class, null));
94         // a simple class, which is not extended
95         result.add(new TestCase(DoNotExtendClass.class, null));
96         // a usual class, which is extended
97         result.add(new TestCase(SingleSubclassedClass.class, null));
98         return result;
99     }
100 
runTest(TestCase tcase)101     private void runTest(TestCase tcase) {
102         System.out.println(tcase);
103         HotSpotResolvedObjectType resolvedIface = CompilerToVMHelper
104                 .lookupTypeHelper(Utils.toJVMTypeSignature(tcase.anInterface),
105                         getClass(), /* resolve = */ true);
106         if (!resolvedIface.isInterface()) {
107             try {
108                 CompilerToVMHelper.getImplementor(resolvedIface);
109                 Asserts.fail("Expected " + IllegalArgumentException.class.getName());
110             } catch (IllegalArgumentException e) {
111             }
112             return;
113         }
114         HotSpotResolvedObjectType resolvedImplementer = CompilerToVMHelper
115                 .getImplementor(resolvedIface);
116         HotSpotResolvedObjectType resolvedExpected = null;
117         if (tcase.expectedImplementer != null) {
118             resolvedExpected = CompilerToVMHelper.lookupTypeHelper(Utils
119                     .toJVMTypeSignature(tcase.expectedImplementer),
120                     getClass(), /* resolve = */ true);
121         }
122         Asserts.assertEQ(resolvedImplementer, resolvedExpected,
123                 "Unexpected implementer for " + tcase.anInterface.getName());
124     }
125 
126     private static class TestCase {
127         public final Class<?> anInterface;
128         public final Class<?> expectedImplementer;
129 
TestCase(Class<?> iface, Class<?> expectedImplementer)130         public TestCase(Class<?> iface, Class<?> expectedImplementer) {
131             this.anInterface = iface;
132             this.expectedImplementer = expectedImplementer;
133         }
134 
135         @Override
toString()136         public String toString() {
137             return String.format("CASE: interface=%s, expected=%s",
138                     anInterface.getName(),
139                     expectedImplementer == null
140                             ? null
141                             : expectedImplementer.getName());
142         }
143     }
144 }
145