comparison jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaMethod.java @ 22672:1bbd4a7c274b

Rename jdk.internal.jvmci to jdk.vm.ci
author Tom Rodriguez <tom.rodriguez@oracle.com>
date Thu, 08 Oct 2015 17:28:41 -0700
parents jvmci/jdk.internal.jvmci.runtime.test/src/jdk/internal/jvmci/runtime/test/TestResolvedJavaMethod.java@9f24bf92ee94
children 995af926c06b
comparison
equal deleted inserted replaced
22671:97f30e4d0e95 22672:1bbd4a7c274b
1 /*
2 * Copyright (c) 2012, 2015, 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 * @compile TestResolvedJavaMethod.java MethodUniverse.java TypeUniverse.java TestMetaAccessProvider.java
27 * @run junit jdk.vm.ci.runtime.test.TestResolvedJavaMethod
28 */
29
30 package jdk.vm.ci.runtime.test;
31
32 import static org.junit.Assert.assertEquals;
33 import static org.junit.Assert.assertFalse;
34 import static org.junit.Assert.assertNotNull;
35 import static org.junit.Assert.assertTrue;
36
37 import java.lang.annotation.Annotation;
38 import java.lang.annotation.ElementType;
39 import java.lang.annotation.Retention;
40 import java.lang.annotation.RetentionPolicy;
41 import java.lang.annotation.Target;
42 import java.lang.invoke.MethodHandle;
43 import java.lang.reflect.Constructor;
44 import java.lang.reflect.Member;
45 import java.lang.reflect.Method;
46 import java.lang.reflect.Modifier;
47 import java.lang.reflect.Type;
48 import java.util.Arrays;
49 import java.util.HashMap;
50 import java.util.HashSet;
51 import java.util.Map;
52 import java.util.Set;
53
54 import jdk.vm.ci.meta.ConstantPool;
55 import jdk.vm.ci.meta.ExceptionHandler;
56 import jdk.vm.ci.meta.ResolvedJavaMethod;
57 import jdk.vm.ci.meta.ResolvedJavaType;
58
59 import org.junit.Assert;
60 import org.junit.Test;
61
62 /**
63 * Tests for {@link ResolvedJavaMethod}.
64 */
65 public class TestResolvedJavaMethod extends MethodUniverse {
66
67 public TestResolvedJavaMethod() {
68 }
69
70 /**
71 * @see ResolvedJavaMethod#getCode()
72 */
73 @Test
74 public void getCodeTest() {
75 for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
76 ResolvedJavaMethod m = e.getValue();
77 byte[] code = m.getCode();
78 if (code == null) {
79 assertTrue(m.getCodeSize() == 0);
80 } else {
81 if (m.isAbstract()) {
82 assertTrue(code.length == 0);
83 } else if (!m.isNative()) {
84 assertTrue(code.length > 0);
85 }
86 }
87 }
88 }
89
90 /**
91 * @see ResolvedJavaMethod#getCodeSize()
92 */
93 @Test
94 public void getCodeSizeTest() {
95 for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
96 ResolvedJavaMethod m = e.getValue();
97 int codeSize = m.getCodeSize();
98 if (m.isAbstract()) {
99 assertTrue(codeSize == 0);
100 } else if (!m.isNative()) {
101 assertTrue(codeSize > 0);
102 }
103 }
104 }
105
106 @Test
107 public void getModifiersTest() {
108 for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
109 ResolvedJavaMethod m = e.getValue();
110 int expected = e.getKey().getModifiers();
111 int actual = m.getModifiers();
112 assertEquals(String.format("%s: 0x%x != 0x%x", m, expected, actual), expected, actual);
113 }
114 for (Map.Entry<Constructor<?>, ResolvedJavaMethod> e : constructors.entrySet()) {
115 ResolvedJavaMethod m = e.getValue();
116 int expected = e.getKey().getModifiers();
117 int actual = m.getModifiers();
118 assertEquals(String.format("%s: 0x%x != 0x%x", m, expected, actual), expected, actual);
119 }
120 }
121
122 /**
123 * @see ResolvedJavaMethod#isClassInitializer()
124 */
125 @Test
126 public void isClassInitializerTest() {
127 for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
128 // Class initializers are hidden from reflection
129 ResolvedJavaMethod m = e.getValue();
130 assertFalse(m.isClassInitializer());
131 }
132 for (Map.Entry<Constructor<?>, ResolvedJavaMethod> e : constructors.entrySet()) {
133 ResolvedJavaMethod m = e.getValue();
134 assertFalse(m.isClassInitializer());
135 }
136 }
137
138 @Test
139 public void isConstructorTest() {
140 for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
141 ResolvedJavaMethod m = e.getValue();
142 assertFalse(m.isConstructor());
143 }
144 for (Map.Entry<Constructor<?>, ResolvedJavaMethod> e : constructors.entrySet()) {
145 ResolvedJavaMethod m = e.getValue();
146 assertTrue(m.isConstructor());
147 }
148 }
149
150 @Test
151 public void isSyntheticTest() {
152 for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
153 ResolvedJavaMethod m = e.getValue();
154 assertEquals(e.getKey().isSynthetic(), m.isSynthetic());
155 }
156 for (Map.Entry<Constructor<?>, ResolvedJavaMethod> e : constructors.entrySet()) {
157 ResolvedJavaMethod m = e.getValue();
158 assertEquals(e.getKey().isSynthetic(), m.isSynthetic());
159 }
160 }
161
162 @Test
163 public void isBridgeTest() {
164 for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
165 ResolvedJavaMethod m = e.getValue();
166 assertEquals(e.getKey().isBridge(), m.isBridge());
167 }
168 for (Map.Entry<Constructor<?>, ResolvedJavaMethod> e : constructors.entrySet()) {
169 ResolvedJavaMethod m = e.getValue();
170 assertEquals(false, m.isBridge());
171 }
172 }
173
174 @Test
175 public void isVarArgsTest() {
176 for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
177 ResolvedJavaMethod m = e.getValue();
178 assertEquals(e.getKey().isVarArgs(), m.isVarArgs());
179 }
180 for (Map.Entry<Constructor<?>, ResolvedJavaMethod> e : constructors.entrySet()) {
181 ResolvedJavaMethod m = e.getValue();
182 assertEquals(e.getKey().isVarArgs(), m.isVarArgs());
183 }
184 }
185
186 @Test
187 public void isSynchronizedTest() {
188 for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
189 ResolvedJavaMethod m = e.getValue();
190 assertEquals(Modifier.isSynchronized(e.getKey().getModifiers()), m.isSynchronized());
191 }
192 for (Map.Entry<Constructor<?>, ResolvedJavaMethod> e : constructors.entrySet()) {
193 ResolvedJavaMethod m = e.getValue();
194 assertEquals(Modifier.isSynchronized(e.getKey().getModifiers()), m.isSynchronized());
195 }
196 }
197
198 @Test
199 public void canBeStaticallyBoundTest() {
200 for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
201 ResolvedJavaMethod m = e.getValue();
202 assertEquals(m.canBeStaticallyBound(), canBeStaticallyBound(e.getKey()));
203 }
204 for (Map.Entry<Constructor<?>, ResolvedJavaMethod> e : constructors.entrySet()) {
205 ResolvedJavaMethod m = e.getValue();
206 assertEquals(m.canBeStaticallyBound(), canBeStaticallyBound(e.getKey()));
207 }
208 }
209
210 private static boolean canBeStaticallyBound(Member method) {
211 int modifiers = method.getModifiers();
212 return (Modifier.isFinal(modifiers) || Modifier.isPrivate(modifiers) || Modifier.isStatic(modifiers) || Modifier.isFinal(method.getDeclaringClass().getModifiers())) &&
213 !Modifier.isAbstract(modifiers);
214 }
215
216 private static String methodWithExceptionHandlers(String p1, Object o2) {
217 try {
218 return p1.substring(100) + o2.toString();
219 } catch (IndexOutOfBoundsException e) {
220 e.printStackTrace();
221 } catch (NullPointerException e) {
222 e.printStackTrace();
223 } catch (RuntimeException e) {
224 e.printStackTrace();
225 }
226 return null;
227 }
228
229 @Test
230 public void getExceptionHandlersTest() throws NoSuchMethodException {
231 ResolvedJavaMethod method = metaAccess.lookupJavaMethod(getClass().getDeclaredMethod("methodWithExceptionHandlers", String.class, Object.class));
232 ExceptionHandler[] handlers = method.getExceptionHandlers();
233 assertNotNull(handlers);
234 assertEquals(handlers.length, 3);
235 handlers[0].getCatchType().equals(metaAccess.lookupJavaType(IndexOutOfBoundsException.class));
236 handlers[1].getCatchType().equals(metaAccess.lookupJavaType(NullPointerException.class));
237 handlers[2].getCatchType().equals(metaAccess.lookupJavaType(RuntimeException.class));
238 }
239
240 private static String nullPointerExceptionOnFirstLine(Object o, String ignored) {
241 return o.toString() + ignored;
242 }
243
244 @Test
245 public void asStackTraceElementTest() throws NoSuchMethodException {
246 try {
247 nullPointerExceptionOnFirstLine(null, "ignored");
248 Assert.fail("should not reach here");
249 } catch (NullPointerException e) {
250 StackTraceElement expected = e.getStackTrace()[0];
251 ResolvedJavaMethod method = metaAccess.lookupJavaMethod(getClass().getDeclaredMethod("nullPointerExceptionOnFirstLine", Object.class, String.class));
252 StackTraceElement actual = method.asStackTraceElement(0);
253 assertEquals(expected, actual);
254 }
255 }
256
257 @Test
258 public void getConstantPoolTest() {
259 for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
260 ResolvedJavaMethod m = e.getValue();
261 ConstantPool cp = m.getConstantPool();
262 assertTrue(cp.length() > 0);
263 }
264 }
265
266 @Test(timeout = 1000L)
267 public void getAnnotationTest() throws NoSuchMethodException {
268 ResolvedJavaMethod method = metaAccess.lookupJavaMethod(getClass().getDeclaredMethod("getAnnotationTest"));
269 Test annotation = method.getAnnotation(Test.class);
270 assertNotNull(annotation);
271 assertEquals(1000L, annotation.timeout());
272 }
273
274 @Test(timeout = 1000L)
275 public void getAnnotationsTest() throws NoSuchMethodException {
276 ResolvedJavaMethod method = metaAccess.lookupJavaMethod(getClass().getDeclaredMethod("getAnnotationsTest"));
277 Annotation[] annotations = method.getAnnotations();
278 assertNotNull(annotations);
279 assertEquals(1, annotations.length);
280 assertEquals(1000L, ((Test) annotations[0]).timeout());
281 }
282
283 @Retention(RetentionPolicy.RUNTIME)
284 @Target(ElementType.PARAMETER)
285 @interface NonNull {
286 }
287
288 @Retention(RetentionPolicy.RUNTIME)
289 @Target(ElementType.PARAMETER)
290 @interface Special {
291 }
292
293 private static native void methodWithAnnotatedParameters(@NonNull HashMap<String, String> p1, @Special @NonNull Class<? extends Annotation> p2);
294
295 @Test
296 public void getParameterAnnotationsTest() throws NoSuchMethodException {
297 ResolvedJavaMethod method = metaAccess.lookupJavaMethod(getClass().getDeclaredMethod("methodWithAnnotatedParameters", HashMap.class, Class.class));
298 Annotation[][] annotations = method.getParameterAnnotations();
299 assertEquals(2, annotations.length);
300 assertEquals(1, annotations[0].length);
301 assertEquals(NonNull.class, annotations[0][0].annotationType());
302 assertEquals(2, annotations[1].length);
303 assertEquals(Special.class, annotations[1][0].annotationType());
304 assertEquals(NonNull.class, annotations[1][1].annotationType());
305 }
306
307 @Test
308 public void getGenericParameterTypesTest() throws NoSuchMethodException {
309 ResolvedJavaMethod method = metaAccess.lookupJavaMethod(getClass().getDeclaredMethod("methodWithAnnotatedParameters", HashMap.class, Class.class));
310 Type[] genericParameterTypes = method.getGenericParameterTypes();
311 assertEquals(2, genericParameterTypes.length);
312 assertEquals("java.util.HashMap<java.lang.String, java.lang.String>", genericParameterTypes[0].toString());
313 assertEquals("java.lang.Class<? extends java.lang.annotation.Annotation>", genericParameterTypes[1].toString());
314 }
315
316 @Test
317 public void getMaxLocalsTest() throws NoSuchMethodException {
318 ResolvedJavaMethod method1 = metaAccess.lookupJavaMethod(getClass().getDeclaredMethod("methodWithAnnotatedParameters", HashMap.class, Class.class));
319 ResolvedJavaMethod method2 = metaAccess.lookupJavaMethod(getClass().getDeclaredMethod("nullPointerExceptionOnFirstLine", Object.class, String.class));
320 assertEquals(0, method1.getMaxLocals());
321 assertEquals(2, method2.getMaxLocals());
322
323 }
324
325 @Test
326 public void getMaxStackSizeTest() throws NoSuchMethodException {
327 ResolvedJavaMethod method1 = metaAccess.lookupJavaMethod(getClass().getDeclaredMethod("methodWithAnnotatedParameters", HashMap.class, Class.class));
328 ResolvedJavaMethod method2 = metaAccess.lookupJavaMethod(getClass().getDeclaredMethod("nullPointerExceptionOnFirstLine", Object.class, String.class));
329 assertEquals(0, method1.getMaxStackSize());
330 // some versions of javac produce bytecode with a stacksize of 2 for this method
331 // JSR 292 also sometimes need one more stack slot
332 int method2StackSize = method2.getMaxStackSize();
333 assertTrue(2 <= method2StackSize && method2StackSize <= 4);
334 }
335
336 @Test
337 public void isDefaultTest() {
338 for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
339 ResolvedJavaMethod m = e.getValue();
340 assertEquals(e.getKey().isDefault(), m.isDefault());
341 }
342 for (Map.Entry<Constructor<?>, ResolvedJavaMethod> e : constructors.entrySet()) {
343 ResolvedJavaMethod m = e.getValue();
344 assertFalse(m.isDefault());
345 }
346 }
347
348 @Test
349 public void hasReceiverTest() {
350 for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
351 ResolvedJavaMethod m = e.getValue();
352 assertTrue(m.hasReceiver() != Modifier.isStatic(e.getKey().getModifiers()));
353 }
354 for (Map.Entry<Constructor<?>, ResolvedJavaMethod> e : constructors.entrySet()) {
355 ResolvedJavaMethod m = e.getValue();
356 assertTrue(m.hasReceiver());
357 }
358 }
359
360 @Test
361 public void hasBytecodesTest() {
362 for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
363 ResolvedJavaMethod m = e.getValue();
364 assertTrue(m.hasBytecodes() == (m.isConcrete() && !m.isNative()));
365 }
366 for (Map.Entry<Constructor<?>, ResolvedJavaMethod> e : constructors.entrySet()) {
367 ResolvedJavaMethod m = e.getValue();
368 assertTrue(m.hasBytecodes());
369 }
370 }
371
372 @Test
373 public void isJavaLangObjectInitTest() throws NoSuchMethodException {
374 ResolvedJavaMethod method = metaAccess.lookupJavaMethod(Object.class.getConstructor());
375 assertTrue(method.isJavaLangObjectInit());
376 for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
377 ResolvedJavaMethod m = e.getValue();
378 assertFalse(m.isJavaLangObjectInit());
379 }
380 for (Map.Entry<Constructor<?>, ResolvedJavaMethod> e : constructors.entrySet()) {
381 ResolvedJavaMethod m = e.getValue();
382 Constructor<?> key = e.getKey();
383 if (key.getDeclaringClass() == Object.class && key.getParameters().length == 0) {
384 assertTrue(m.isJavaLangObjectInit());
385 } else {
386 assertFalse(m.isJavaLangObjectInit());
387 }
388 }
389 }
390
391 @Test
392 public void isSignaturePolymorphicTest() {
393 ResolvedJavaType methodHandleType = metaAccess.lookupJavaType(MethodHandle.class);
394 assertTrue(ResolvedJavaMethod.isSignaturePolymorphic(methodHandleType, "invokeExact", metaAccess));
395 assertTrue(ResolvedJavaMethod.isSignaturePolymorphic(methodHandleType, "invoke", metaAccess));
396 assertTrue(ResolvedJavaMethod.isSignaturePolymorphic(methodHandleType, "invokeBasic", metaAccess));
397 assertTrue(ResolvedJavaMethod.isSignaturePolymorphic(methodHandleType, "linkToVirtual", metaAccess));
398 assertTrue(ResolvedJavaMethod.isSignaturePolymorphic(methodHandleType, "linkToStatic", metaAccess));
399 assertTrue(ResolvedJavaMethod.isSignaturePolymorphic(methodHandleType, "linkToSpecial", metaAccess));
400 assertTrue(ResolvedJavaMethod.isSignaturePolymorphic(methodHandleType, "linkToInterface", metaAccess));
401 assertFalse(ResolvedJavaMethod.isSignaturePolymorphic(methodHandleType, "type", metaAccess));
402 assertFalse(ResolvedJavaMethod.isSignaturePolymorphic(metaAccess.lookupJavaType(Object.class), "toString", metaAccess));
403 }
404
405 private Method findTestMethod(Method apiMethod) {
406 String testName = apiMethod.getName() + "Test";
407 for (Method m : getClass().getDeclaredMethods()) {
408 if (m.getName().equals(testName) && m.getAnnotation(Test.class) != null) {
409 return m;
410 }
411 }
412 return null;
413 }
414
415 // @formatter:off
416 private static final String[] untestedApiMethods = {
417 "invoke",
418 "newInstance",
419 "getDeclaringClass",
420 "getEncoding",
421 "getProfilingInfo",
422 "reprofile",
423 "getCompilerStorage",
424 "canBeInlined",
425 "shouldBeInlined",
426 "getLineNumberTable",
427 "getLocalVariableTable",
428 "isInVirtualMethodTable",
429 "toParameterTypes",
430 "getParameterAnnotation",
431 "getSpeculationLog",
432 "isFinal",
433 "$jacocoInit"
434 };
435 // @formatter:on
436
437 /**
438 * Ensures that any new methods added to {@link ResolvedJavaMethod} either have a test written
439 * for them or are added to {@link #untestedApiMethods}.
440 */
441 @Test
442 public void testCoverage() {
443 Set<String> known = new HashSet<>(Arrays.asList(untestedApiMethods));
444 for (Method m : ResolvedJavaMethod.class.getDeclaredMethods()) {
445 if (Modifier.isStatic(m.getModifiers())) {
446 continue;
447 }
448 if (findTestMethod(m) == null) {
449 assertTrue("test missing for " + m, known.contains(m.getName()));
450 } else {
451 assertFalse("test should be removed from untestedApiMethods" + m, known.contains(m.getName()));
452 }
453 }
454 }
455 }