1 /* 2 * Copyright (c) 2018, 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 /* @test 25 * @summary unit tests for java.lang.invoke.MethodHandles 26 * @library /lib/testlibrary /java/lang/invoke/common 27 * @compile MethodHandlesTest.java MethodHandlesCastFailureTest.java remote/RemoteExample.java 28 * @run junit/othervm/timeout=2500 -XX:+IgnoreUnrecognizedVMOptions 29 * -XX:-VerifyDependencies 30 * -esa 31 * test.java.lang.invoke.MethodHandlesCastFailureTest 32 */ 33 34 package test.java.lang.invoke; 35 36 import org.junit.*; 37 import test.java.lang.invoke.lib.CodeCacheOverflowProcessor; 38 39 import java.lang.invoke.MethodHandle; 40 import java.lang.invoke.MethodHandles; 41 import java.lang.invoke.MethodType; 42 43 import static org.junit.Assert.*; 44 45 public class MethodHandlesCastFailureTest extends MethodHandlesTest { 46 47 @Test // SLOW testCastFailure()48 public void testCastFailure() throws Throwable { 49 CodeCacheOverflowProcessor.runMHTest(this::testCastFailure0); 50 } 51 52 // Android-added: @Ignore as this is a helper for testCastFailure(). 53 @Ignore testCastFailure0()54 public void testCastFailure0() throws Throwable { 55 if (CAN_SKIP_WORKING) return; 56 startTest("testCastFailure"); 57 testCastFailure("cast/argument", 11000); 58 if (CAN_TEST_LIGHTLY) return; 59 testCastFailure("unbox/argument", 11000); 60 testCastFailure("cast/return", 11000); 61 testCastFailure("unbox/return", 11000); 62 } 63 64 static class Surprise { asMethodHandle()65 public MethodHandle asMethodHandle() { 66 return VALUE.bindTo(this); 67 } value(Object x)68 Object value(Object x) { 69 trace("value", x); 70 if (boo != null) return boo; 71 return x; 72 } 73 Object boo; boo(Object x)74 void boo(Object x) { boo = x; } 75 trace(String x, Object y)76 static void trace(String x, Object y) { 77 if (verbosity > 8) System.out.println(x+"="+y); 78 } refIdentity(Object x)79 static Object refIdentity(Object x) { trace("ref.x", x); return x; } boxIdentity(Integer x)80 static Integer boxIdentity(Integer x) { trace("box.x", x); return x; } intIdentity(int x)81 static int intIdentity(int x) { trace("int.x", x); return x; } 82 static MethodHandle VALUE, REF_IDENTITY, BOX_IDENTITY, INT_IDENTITY; 83 static { 84 try { 85 VALUE = PRIVATE.findVirtual( 86 Surprise.class, "value", 87 MethodType.methodType(Object.class, Object.class)); 88 REF_IDENTITY = PRIVATE.findStatic( 89 Surprise.class, "refIdentity", 90 MethodType.methodType(Object.class, Object.class)); 91 BOX_IDENTITY = PRIVATE.findStatic( 92 Surprise.class, "boxIdentity", 93 MethodType.methodType(Integer.class, Integer.class)); 94 INT_IDENTITY = PRIVATE.findStatic( 95 Surprise.class, "intIdentity", 96 MethodType.methodType(int.class, int.class)); 97 } catch (NoSuchMethodException | IllegalAccessException ex) { 98 throw new RuntimeException(ex); 99 } 100 } 101 } 102 103 // Android-added: @Ignore as this is a helper. 104 @Ignore 105 @SuppressWarnings("ConvertToStringSwitch") testCastFailure(String mode, int okCount)106 void testCastFailure(String mode, int okCount) throws Throwable { 107 countTest(false); 108 if (verbosity > 2) System.out.println("mode="+mode); 109 Surprise boo = new Surprise(); 110 MethodHandle identity = Surprise.REF_IDENTITY, surprise0 = boo.asMethodHandle(), surprise = surprise0; 111 if (mode.endsWith("/return")) { 112 if (mode.equals("unbox/return")) { 113 // fail on return to ((Integer)surprise).intValue 114 surprise = surprise.asType(MethodType.methodType(int.class, Object.class)); 115 identity = identity.asType(MethodType.methodType(int.class, Object.class)); 116 } else if (mode.equals("cast/return")) { 117 // fail on return to (Integer)surprise 118 surprise = surprise.asType(MethodType.methodType(Integer.class, Object.class)); 119 identity = identity.asType(MethodType.methodType(Integer.class, Object.class)); 120 } 121 } else if (mode.endsWith("/argument")) { 122 MethodHandle callee = null; 123 if (mode.equals("unbox/argument")) { 124 // fail on handing surprise to int argument 125 callee = Surprise.INT_IDENTITY; 126 } else if (mode.equals("cast/argument")) { 127 // fail on handing surprise to Integer argument 128 callee = Surprise.BOX_IDENTITY; 129 } 130 if (callee != null) { 131 callee = callee.asType(MethodType.genericMethodType(1)); 132 surprise = MethodHandles.filterArguments(callee, 0, surprise); 133 identity = MethodHandles.filterArguments(callee, 0, identity); 134 } 135 } 136 assertNotSame(mode, surprise, surprise0); 137 identity = identity.asType(MethodType.genericMethodType(1)); 138 surprise = surprise.asType(MethodType.genericMethodType(1)); 139 Object x = 42; 140 for (int i = 0; i < okCount; i++) { 141 Object y = identity.invokeExact(x); 142 assertEquals(x, y); 143 Object z = surprise.invokeExact(x); 144 assertEquals(x, z); 145 } 146 boo.boo("Boo!"); 147 Object y = identity.invokeExact(x); 148 assertEquals(x, y); 149 try { 150 Object z = surprise.invokeExact(x); 151 System.out.println("Failed to throw; got z="+z); 152 assertTrue(false); 153 } catch (ClassCastException ex) { 154 if (verbosity > 2) 155 System.out.println("caught "+ex); 156 if (verbosity > 3) 157 ex.printStackTrace(System.out); 158 assertTrue(true); // all is well 159 } 160 } 161 } 162