Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/test/java/lang/invoke/ExplicitCastArgumentsTest.java
47209 views
/*1* Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223import com.oracle.testlibrary.jsr292.Helper;24import java.io.File;25import java.io.Serializable;26import java.lang.invoke.MethodHandle;27import java.lang.invoke.MethodHandles;28import java.lang.invoke.MethodType;29import java.lang.invoke.WrongMethodTypeException;30import java.util.HashMap;31import java.util.Map;32import java.util.Random;33import sun.invoke.util.Wrapper;3435/*36* @test37* @bug 8060483 806674638* @library /lib/testlibrary /lib/testlibrary/jsr29239* @summary unit tests for MethodHandles.explicitCastArguments()40* @run main ExplicitCastArgumentsTest41*/4243/**44* Tests for MethodHandles.explicitCastArguments().45*/46public class ExplicitCastArgumentsTest {4748private static final boolean VERBOSE = Helper.IS_VERBOSE;49private static final Class<?> THIS_CLASS = ExplicitCastArgumentsTest.class;50private static final Random RNG = Helper.RNG;51private static final Map<Wrapper, Object> RANDOM_VALUES = new HashMap<>(9);5253static {54RANDOM_VALUES.put(Wrapper.BOOLEAN, RNG.nextBoolean());55RANDOM_VALUES.put(Wrapper.BYTE, (byte) RNG.nextInt());56RANDOM_VALUES.put(Wrapper.SHORT, (short) RNG.nextInt());57RANDOM_VALUES.put(Wrapper.CHAR, (char) RNG.nextInt());58RANDOM_VALUES.put(Wrapper.INT, RNG.nextInt());59RANDOM_VALUES.put(Wrapper.LONG, RNG.nextLong());60RANDOM_VALUES.put(Wrapper.FLOAT, RNG.nextFloat());61RANDOM_VALUES.put(Wrapper.DOUBLE, RNG.nextDouble());62RANDOM_VALUES.put(Wrapper.OBJECT, new Object());63}6465public static void main(String[] args) throws Throwable {66testVarargsCollector();67testNullRef2Prim();68testRef2Prim();69testPrim2Ref();70testPrim2Prim();71testNonBCPRef2NonBCPRef();72testBCPRef2BCPRef();73testNonBCPRef2BCPRef();74testReturnAny2Void();75testReturnVoid2Any();76testMultipleArgs();77System.out.println("TEST PASSED");78}7980/**81* Dummy method used in {@link #testVarargsCollector} test to form a method82* handle.83*84* @param args - any args85* @return - returns args86*/87public static String[] f(String... args) {88return args;89}9091/**92* Tests that MHs.explicitCastArguments does incorrect type checks for93* VarargsCollector. Bug 8066746.94*95* @throws java.lang.Throwable96*/97public static void testVarargsCollector() throws Throwable {98MethodType mt = MethodType.methodType(String[].class, String[].class);99MethodHandle mh = MethodHandles.publicLookup()100.findStatic(THIS_CLASS, "f", mt);101mh = MethodHandles.explicitCastArguments(mh,102MethodType.methodType(Object.class, Object.class));103mh.invokeWithArguments((Object) (new String[]{"str1", "str2"}));104}105106/**107* Tests that null wrapper reference is successfully converted to primitive108* types. Converted result should be zero for a primitive. Bug 8060483.109*/110public static void testNullRef2Prim() {111for (Wrapper from : Wrapper.values()) {112for (Wrapper to : Wrapper.values()) {113if (from == Wrapper.VOID || to == Wrapper.VOID) {114continue;115}116// MHs.eCA javadoc:117// If T0 is a reference and T1 a primitive, and if the reference118// is null at runtime, a zero value is introduced.119for (TestConversionMode mode : TestConversionMode.values()) {120testConversion(mode, from.wrapperType(),121to.primitiveType(), null, to.zero(), false, null);122}123}124}125}126127/**128* Tests that non-null wrapper reference is successfully converted to129* primitive types.130*/131public static void testRef2Prim() {132for (Wrapper from : Wrapper.values()) {133for (Wrapper to : Wrapper.values()) {134if (from == Wrapper.VOID || to == Wrapper.VOID135|| to == Wrapper.OBJECT) {136continue;137}138Object value = RANDOM_VALUES.get(from);139for (TestConversionMode mode : TestConversionMode.values()) {140if (from != Wrapper.OBJECT) {141Object convValue = to.wrap(value);142testConversion(mode, from.wrapperType(),143to.primitiveType(), value, convValue, false, null);144} else {145testConversion(mode, from.wrapperType(),146to.primitiveType(), value, null,147true, ClassCastException.class);148}149}150}151}152}153154/**155* Tests that primitive is successfully converted to wrapper reference156* types, to the Number type (if possible) and to the Object type.157*/158public static void testPrim2Ref() {159for (Wrapper from : Wrapper.values()) {160for (Wrapper to : Wrapper.values()) {161if (from == Wrapper.VOID || from == Wrapper.OBJECT162|| to == Wrapper.VOID || to == Wrapper.OBJECT) {163continue;164}165Object value = RANDOM_VALUES.get(from);166for (TestConversionMode mode : TestConversionMode.values()) {167if (from == to) {168testConversion(mode, from.primitiveType(),169to.wrapperType(), value, value, false, null);170} else {171testConversion(mode, from.primitiveType(),172to.wrapperType(), value, null, true, ClassCastException.class);173}174if (from != Wrapper.BOOLEAN && from != Wrapper.CHAR) {175testConversion(mode, from.primitiveType(),176Number.class, value, value, false, null);177} else {178testConversion(mode, from.primitiveType(),179Number.class, value, null,180true, ClassCastException.class);181}182testConversion(mode, from.primitiveType(),183Object.class, value, value, false, null);184}185}186}187}188189/**190* Tests that primitive is successfully converted to other primitive type.191*/192public static void testPrim2Prim() {193for (Wrapper from : Wrapper.values()) {194for (Wrapper to : Wrapper.values()) {195if (from == Wrapper.VOID || to == Wrapper.VOID196|| from == Wrapper.OBJECT || to == Wrapper.OBJECT) {197continue;198}199Object value = RANDOM_VALUES.get(from);200Object convValue = to.wrap(value);201for (TestConversionMode mode : TestConversionMode.values()) {202testConversion(mode, from.primitiveType(),203to.primitiveType(), value, convValue, false, null);204}205}206}207}208209/**210* Dummy interface for {@link #testNonBCPRef2Ref} test.211*/212public static interface TestInterface {}213214/**215* Dummy class for {@link #testNonBCPRef2Ref} test.216*/217public static class TestSuperClass implements TestInterface {}218219/**220* Dummy class for {@link #testNonBCPRef2Ref} test.221*/222public static class TestSubClass1 extends TestSuperClass {}223224/**225* Dummy class for {@link #testNonBCPRef2Ref} test.226*/227public static class TestSubClass2 extends TestSuperClass {}228229/**230* Tests non-bootclasspath reference to reference conversions.231*232* @throws java.lang.Throwable233*/234public static void testNonBCPRef2NonBCPRef() throws Throwable {235Class testInterface = TestInterface.class;236Class testSuperClass = TestSuperClass.class;237Class testSubClass1 = TestSubClass1.class;238Class testSubClass2 = TestSubClass2.class;239Object testSuperObj = new TestSuperClass();240Object testObj01 = new TestSubClass1();241Object testObj02 = new TestSubClass2();242Class[] parents = {testInterface, testSuperClass};243Class[] children = {testSubClass1, testSubClass2};244Object[] childInst = {testObj01, testObj02};245for (TestConversionMode mode : TestConversionMode.values()) {246for (Class parent : parents) {247for (int j = 0; j < children.length; j++) {248// Child type to parent type non-null conversion, shoud succeed249testConversion(mode, children[j], parent, childInst[j], childInst[j], false, null);250// Child type to parent type null conversion, shoud succeed251testConversion(mode, children[j], parent, null, null, false, null);252// Parent type to child type non-null conversion with parent253// type instance, should fail254testConversion(mode, parent, children[j], testSuperObj, null, true, ClassCastException.class);255// Parent type to child type non-null conversion with child256// type instance, should succeed257testConversion(mode, parent, children[j], childInst[j], childInst[j], false, null);258// Parent type to child type null conversion, should succeed259testConversion(mode, parent, children[j], null, null, false, null);260}261// Parent type to child type non-null conversion with sibling262// type instance, should fail263testConversion(mode, parent, testSubClass1, testObj02, null, true, ClassCastException.class);264}265// Sibling type non-null conversion, should fail266testConversion(mode, testSubClass1,267testSubClass2, testObj01, null, true,268ClassCastException.class);269// Sibling type null conversion, should succeed270testConversion(mode, testSubClass1,271testSubClass2, null, null, false, null);272}273}274275/**276* Dummy interface for {@link #testNonBCPRef2BCPRef} test.277*/278public static interface TestSerializableInterface extends Serializable {}279280/**281* Dummy class for {@link #testNonBCPRef2BCPRef} test.282*/283public static class TestSerializableClass284implements TestSerializableInterface {}285286/**287* Dummy class for {@link #testNonBCPRef2BCPRef} test.288*/289public static class TestFileChildClass extends File290implements TestSerializableInterface {291public TestFileChildClass(String pathname) {292super(pathname);293}294}295296/**297* Tests non-bootclasspath reference to bootclasspath reference conversions298* and vice-versa.299*300* @throws java.lang.Throwable301*/302public static void testNonBCPRef2BCPRef() throws Throwable {303Class bcpInterface = Serializable.class;304Class bcpSuperClass = File.class;305Class nonBcpInterface = TestSerializableInterface.class;306Class nonBcpSuperSiblingClass = TestSerializableClass.class;307Class nonBcpSubClass = TestFileChildClass.class;308Object bcpSuperObj = new File(".");309Object testSuperSiblingObj = new TestSerializableClass();310Object testSubObj = new TestFileChildClass(".");311Class[] parents = {bcpInterface, bcpSuperClass};312for (TestConversionMode mode : TestConversionMode.values()) {313for (Class parent : parents) {314// Child type to parent type non-null conversion, shoud succeed315testConversion(mode, nonBcpSubClass, parent, testSubObj,316testSubObj, false, null);317// Child type to parent type null conversion, shoud succeed318testConversion(mode, nonBcpSubClass, parent, null, null,319false, null);320// Parent type to child type non-null conversion with parent321// type instance, should fail322testConversion(mode, parent, nonBcpSubClass, bcpSuperObj, null,323true, ClassCastException.class);324// Parent type to child type non-null conversion with child325// type instance, should succeed326testConversion(mode, parent, nonBcpSubClass, testSubObj,327testSubObj, false, null);328// Parent type to child type null conversion, should succeed329testConversion(mode, parent, nonBcpSubClass, null, null,330false, null);331}332// Parent type to child type non-null conversion with333// super sibling type instance, should fail334testConversion(mode, bcpInterface, nonBcpSubClass,335testSuperSiblingObj, null, true, ClassCastException.class);336Class[] siblings = {nonBcpSubClass, bcpSuperClass};337for (Class sibling : siblings) {338// Non-bcp class to bcp/non-bcp sibling class non-null339// conversion with nonBcpSuperSiblingClass instance, should fail340testConversion(mode, nonBcpSuperSiblingClass, sibling,341testSuperSiblingObj, null, true, ClassCastException.class);342// Non-bcp class to bcp/non-bcp sibling class null conversion,343// should succeed344testConversion(mode, nonBcpSuperSiblingClass, sibling,345null, null, false, null);346// Non-bcp interface to bcp/non-bcp sibling class non-null347// conversion with nonBcpSubClass instance, should succeed348testConversion(mode, nonBcpInterface, sibling, testSubObj,349testSubObj, false, null);350// Non-bcp interface to bcp/non-bcp sibling class351// null conversion, should succeed352testConversion(mode, nonBcpInterface, sibling, null, null,353false, null);354// Non-bcp interface to bcp/non-bcp sibling class non-null355// conversion with nonBcpSuperSiblingClass instance, should fail356testConversion(mode, nonBcpInterface, sibling,357testSuperSiblingObj, testSubObj,358true, ClassCastException.class);359}360}361}362363/**364* Tests bootclasspath reference to reference conversions.365*/366public static void testBCPRef2BCPRef() {367Class bcpInterface = CharSequence.class;368Class bcpSubClass1 = String.class;369Class bcpSubClass2 = StringBuffer.class;370Object testObj01 = new String("test");371Object testObj02 = new StringBuffer("test");372Class[] children = {bcpSubClass1, bcpSubClass2};373Object[] childInst = {testObj01, testObj02};374for (TestConversionMode mode : TestConversionMode.values()) {375for (int i = 0; i < children.length; i++) {376// Child type to parent type non-null conversion, shoud succeed377testConversion(mode, children[i], bcpInterface, childInst[i],378childInst[i], false, null);379// Child type to parent type null conversion, shoud succeed380testConversion(mode, children[i], bcpInterface, null,381null, false, null);382// Parent type to child type non-null conversion with child383// type instance, should succeed384testConversion(mode, bcpInterface,385children[i], childInst[i], childInst[i], false, null);386// Parent type to child type null conversion, should succeed387testConversion(mode, bcpInterface,388children[i], null, null, false, null);389}390// Sibling type non-null conversion, should fail391testConversion(mode, bcpSubClass1,392bcpSubClass2, testObj01, null, true,393ClassCastException.class);394// Sibling type null conversion, should succeed395testConversion(mode, bcpSubClass1,396bcpSubClass2, null, null, false, null);397// Parent type to child type non-null conversion with sibling398// type instance, should fail399testConversion(mode, bcpInterface, bcpSubClass1, testObj02,400null, true, ClassCastException.class);401}402}403404/**405* Dummy method used in {@link #testReturnAny2Void} and406* {@link #testReturnVoid2Any} tests to form a method handle.407*/408public static void retVoid() {}409410/**411* Tests that non-null any return is successfully converted to non-type412* void.413*/414public static void testReturnAny2Void() {415for (Wrapper from : Wrapper.values()) {416testConversion(TestConversionMode.RETURN_VALUE, from.wrapperType(),417void.class, RANDOM_VALUES.get(from),418null, false, null);419testConversion(TestConversionMode.RETURN_VALUE, from.primitiveType(),420void.class, RANDOM_VALUES.get(from),421null, false, null);422}423}424425/**426* Tests that void return is successfully converted to primitive and427* reference. Result should be zero for primitives and null for references.428*/429public static void testReturnVoid2Any() {430for (Wrapper to : Wrapper.values()) {431testConversion(TestConversionMode.RETURN_VALUE, void.class,432to.primitiveType(), null,433to.zero(), false, null);434testConversion(TestConversionMode.RETURN_VALUE, void.class,435to.wrapperType(), null,436null, false, null);437}438}439440private static void checkForWrongMethodTypeException(MethodHandle mh, MethodType mt) {441try {442MethodHandles.explicitCastArguments(mh, mt);443throw new AssertionError("Expected WrongMethodTypeException is not thrown");444} catch (WrongMethodTypeException wmte) {445if (VERBOSE) {446System.out.printf("Expected exception %s: %s\n",447wmte.getClass(), wmte.getMessage());448}449}450}451452/**453* Tests that MHs.eCA method works correctly with MHs with multiple arguments.454* @throws Throwable455*/456public static void testMultipleArgs() throws Throwable {457int arity = 1 + RNG.nextInt(Helper.MAX_ARITY / 2 - 2);458int arityMinus = RNG.nextInt(arity);459int arityPlus = arity + RNG.nextInt(Helper.MAX_ARITY / 2 - arity) + 1;460MethodType mType = Helper.randomMethodTypeGenerator(arity);461MethodType mTypeNew = Helper.randomMethodTypeGenerator(arity);462MethodType mTypeNewMinus = Helper.randomMethodTypeGenerator(arityMinus);463MethodType mTypeNewPlus = Helper.randomMethodTypeGenerator(arityPlus);464Class<?> rType = mType.returnType();465MethodHandle original;466if (rType.equals(void.class)) {467MethodType mt = MethodType.methodType(void.class);468original = MethodHandles.publicLookup()469.findStatic(THIS_CLASS, "retVoid", mt);470} else {471Object rValue = Helper.castToWrapper(1, rType);472original = MethodHandles.constant(rType, rValue);473}474original = Helper.addTrailingArgs(original, arity, mType.parameterList());475MethodHandle target = MethodHandles476.explicitCastArguments(original, mTypeNew);477Object[] parList = Helper.randomArgs(mTypeNew.parameterList());478for (int i = 0; i < parList.length; i++) {479if (parList[i] instanceof String) {480parList[i] = null; //getting rid of Stings produced by randomArgs481}482}483target.invokeWithArguments(parList);484checkForWrongMethodTypeException(original, mTypeNewMinus);485checkForWrongMethodTypeException(original, mTypeNewPlus);486}487488/**489* Enumeration of test conversion modes.490*/491public enum TestConversionMode {492RETURN_VALUE,493ARGUMENT;494}495496/**497* Tests type and value conversion. Comparing with the given expected result.498*499* @param mode - test conversion mode. See {@link #TestConversionMode}.500* @param from - source type.501* @param to - destination type.502* @param param - value to be converted.503* @param expectedResult - expected value after conversion.504* @param failureExpected - true if conversion failure expected.505* @param expectedException - expected exception class if506* {@code failureExpected} is true.507*/508public static void testConversion(TestConversionMode mode,509Class<?> from, Class<?> to, Object param,510Object expectedResult, boolean failureExpected,511Class<? extends Throwable> expectedException) {512if (VERBOSE) {513System.out.printf("Testing return value conversion: "514+ "%-10s => %-10s: %5s: ", from.getSimpleName(),515to.getSimpleName(), param);516}517MethodHandle original = null;518MethodType newType = null;519switch (mode) {520case RETURN_VALUE:521if (from.equals(void.class)) {522MethodType mt = MethodType.methodType(void.class);523try {524original = MethodHandles.publicLookup()525.findStatic(THIS_CLASS, "retVoid", mt);526} catch (NoSuchMethodException | IllegalAccessException ex) {527throw new Error("Unexpected issue", ex);528}529} else {530original = MethodHandles.constant(from, param);531}532newType = original.type().changeReturnType(to);533break;534case ARGUMENT:535if (from.equals(void.class) || to.equals(void.class)) {536throw new Error("Test issue: argument conversion does not"537+ " work with non-type void");538}539original = MethodHandles.identity(to);540newType = original.type().changeParameterType(0, from);541break;542default:543String msg = String.format("Test issue: unknown test"544+ " convertion mode %s.", mode.name());545throw new Error(msg);546}547try {548MethodHandle target = MethodHandles549.explicitCastArguments(original, newType);550Object result;551switch (mode) {552case RETURN_VALUE:553result = target.invokeWithArguments();554break;555case ARGUMENT:556result = target.invokeWithArguments(param);557break;558default:559String msg = String.format("Test issue: unknown test"560+ " convertion mode %s.", mode.name());561throw new Error(msg);562}563if (!failureExpected564&& (expectedResult != null && !expectedResult.equals(result)565|| expectedResult == null && result != null)) {566String msg = String.format("Conversion result %s is not equal"567+ " to the expected result %10s",568result, expectedResult);569throw new AssertionError(msg);570}571if (VERBOSE) {572String resultStr;573if (result != null) {574resultStr = String.format("Converted value and type are"575+ " %10s (%10s)", "'" + result + "'",576result.getClass().getSimpleName());577} else {578resultStr = String.format("Converted value is %10s", result);579}580System.out.println(resultStr);581}582if (failureExpected) {583String msg = String.format("No exception thrown while testing"584+ " return value conversion: %10s => %10s;"585+ " parameter: %10s",586from, to, param);587throw new AssertionError(msg);588}589} catch (AssertionError e) {590throw e; // report test failure591} catch (Throwable e) {592if (VERBOSE) {593System.out.printf("%s: %s\n", e.getClass(), e.getMessage());594}595if (!failureExpected || !e.getClass().equals(expectedException)) {596String msg = String.format("Unexpected exception was thrown"597+ " while testing return value conversion:"598+ " %s => %s; parameter: %s", from, to, param);599throw new AssertionError(msg, e);600}601}602}603}604605606