< prev index next >

test/java/lang/invoke/ExplicitCastArgumentsTest.java

Print this page


   1 /*
   2  * Copyright (c) 2014, 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 package java.lang.invoke;
  25 








  26 import sun.invoke.util.Wrapper;
  27 
  28 /* @test




  29  * @summary unit tests for MethodHandles.explicitCastArguments()
  30  *
  31  * @run main/bootclasspath java.lang.invoke.ExplicitCastArgumentsTest



  32  */
  33 public class ExplicitCastArgumentsTest {
  34     private static final boolean VERBOSE = Boolean.getBoolean("verbose");

  35     private static final Class<?> THIS_CLASS = ExplicitCastArgumentsTest.class;














  36 
  37     public static void main(String[] args) throws Throwable {
  38         testVarargsCollector();

  39         testRef2Prim();








  40         System.out.println("TEST PASSED");
  41     }
  42 
  43     public static String[] f(String... args) { return args; }









  44 






  45     public static void testVarargsCollector() throws Throwable {
  46         MethodType mt = MethodType.methodType(String[].class, String[].class);
  47         MethodHandle mh = MethodHandles.publicLookup().findStatic(THIS_CLASS, "f", mt);
  48         mh = MethodHandles.explicitCastArguments(mh, MethodType.methodType(Object.class, Object.class));
  49         mh.invokeWithArguments((Object)(new String[] {"str1", "str2"}));


  50     }
  51 
  52     public static void testRef2Prim() throws Throwable {




  53         for (Wrapper from : Wrapper.values()) {
  54             for (Wrapper to : Wrapper.values()) {
  55                 if (from == Wrapper.VOID || to == Wrapper.VOID) continue;
  56                 testRef2Prim(from, to);








  57             }
  58         }
  59     }
  60 
  61     public static void testRef2Prim(Wrapper from, Wrapper to) throws Throwable {
  62         // MHs.eCA javadoc:
  63         //    If T0 is a reference and T1 a primitive, and if the reference is null at runtime, a zero value is introduced.
  64         test(from.wrapperType(), to.primitiveType(), null, false);



































































































































































  65     }
  66 
  67     public static void test(Class<?> from, Class<?> to, Object param, boolean failureExpected) throws Throwable {
  68         if (VERBOSE) System.out.printf("%-10s => %-10s: %5s: ", from.getSimpleName(), to.getSimpleName(), param);
































































  69 
  70         MethodHandle original = MethodHandles.identity(from);
  71         MethodType newType = original.type().changeReturnType(to);










































































  72 

  73         try {
  74             MethodHandle target = MethodHandles.explicitCastArguments(original, newType);
  75             Object result = target.invokeWithArguments(param);



















































  76 











































































  77             if (VERBOSE) {
  78                 String resultStr;
  79                 if (result != null) {
  80                     resultStr = String.format("%10s (%10s)", "'"+result+"'", result.getClass().getSimpleName());


  81                 } else {
  82                     resultStr = String.format("%10s", result);
  83                 }
  84                 System.out.println(resultStr);
  85             }
  86 
  87             if (failureExpected) {
  88                 String msg = String.format("No exception thrown: %s => %s; parameter: %s", from, to, param);



  89                 throw new AssertionError(msg);
  90             }
  91         } catch (AssertionError e) {
  92             throw e; // report test failure
  93         } catch (Throwable e) {
  94             if (VERBOSE) System.out.printf("%s: %s\n", e.getClass(), e.getMessage());
  95             if (!failureExpected) {
  96                 String msg = String.format("Unexpected exception was thrown: %s => %s; parameter: %s", from, to, param);




  97                 throw new AssertionError(msg, e);
  98             }
  99         }
 100     }
 101 }
   1 /*
   2  * Copyright (c) 2014, 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 import com.oracle.testlibrary.jsr292.Helper;
  25 import java.io.File;
  26 import java.io.Serializable;
  27 import java.lang.invoke.MethodHandle;
  28 import java.lang.invoke.MethodHandles;
  29 import java.lang.invoke.MethodType;
  30 import java.lang.invoke.WrongMethodTypeException;
  31 import java.util.HashMap;
  32 import java.util.Map;
  33 import java.util.Random;
  34 import sun.invoke.util.Wrapper;
  35 
  36 /*
  37  * @test
  38  * @bug 8060483 8066746
  39  * @key randomness
  40  * @library /lib/testlibrary /lib/testlibrary/jsr292
  41  * @summary unit tests for MethodHandles.explicitCastArguments()
  42  * @run main ExplicitCastArgumentsTest
  43  */
  44 
  45 /**
  46  * Tests for MethodHandles.explicitCastArguments().
  47  */
  48 public class ExplicitCastArgumentsTest {
  49 
  50     private static final boolean VERBOSE = Helper.IS_VERBOSE;
  51     private static final Class<?> THIS_CLASS = ExplicitCastArgumentsTest.class;
  52     private static final Random RNG = Helper.RNG;
  53     private static final Map<Wrapper, Object> RANDOM_VALUES = new HashMap<>(9);
  54 
  55     static {
  56         RANDOM_VALUES.put(Wrapper.BOOLEAN, RNG.nextBoolean());
  57         RANDOM_VALUES.put(Wrapper.BYTE, (byte) RNG.nextInt());
  58         RANDOM_VALUES.put(Wrapper.SHORT, (short) RNG.nextInt());
  59         RANDOM_VALUES.put(Wrapper.CHAR, (char) RNG.nextInt());
  60         RANDOM_VALUES.put(Wrapper.INT, RNG.nextInt());
  61         RANDOM_VALUES.put(Wrapper.LONG, RNG.nextLong());
  62         RANDOM_VALUES.put(Wrapper.FLOAT, RNG.nextFloat());
  63         RANDOM_VALUES.put(Wrapper.DOUBLE, RNG.nextDouble());
  64         RANDOM_VALUES.put(Wrapper.OBJECT, new Object());
  65     }
  66 
  67     public static void main(String[] args) throws Throwable {
  68         testVarargsCollector();
  69         testNullRef2Prim();
  70         testRef2Prim();
  71         testPrim2Ref();
  72         testPrim2Prim();
  73         testNonBCPRef2NonBCPRef();
  74         testBCPRef2BCPRef();
  75         testNonBCPRef2BCPRef();
  76         testReturnAny2Void();
  77         testReturnVoid2Any();
  78         testMultipleArgs();
  79         System.out.println("TEST PASSED");
  80     }
  81 
  82     /**
  83      * Dummy method used in {@link #testVarargsCollector} test to form a method
  84      * handle.
  85      *
  86      * @param args - any args
  87      * @return - returns args
  88      */
  89     public static String[] f(String... args) {
  90         return args;
  91     }
  92 
  93     /**
  94      * Tests that MHs.explicitCastArguments does incorrect type checks for
  95      * VarargsCollector. Bug 8066746.
  96      *
  97      * @throws java.lang.Throwable
  98      */
  99     public static void testVarargsCollector() throws Throwable {
 100         MethodType mt = MethodType.methodType(String[].class, String[].class);
 101         MethodHandle mh = MethodHandles.publicLookup()
 102                 .findStatic(THIS_CLASS, "f", mt);
 103         mh = MethodHandles.explicitCastArguments(mh,
 104                 MethodType.methodType(Object.class, Object.class));
 105         mh.invokeWithArguments((Object) (new String[]{"str1", "str2"}));
 106     }
 107 
 108     /**
 109      * Tests that null wrapper reference is successfully converted to primitive
 110      * types. Converted result should be zero for a primitive. Bug 8060483.
 111      */
 112     public static void testNullRef2Prim() {
 113         for (Wrapper from : Wrapper.values()) {
 114             for (Wrapper to : Wrapper.values()) {
 115                 if (from == Wrapper.VOID || to == Wrapper.VOID) {
 116                     continue;
 117                 }
 118                 // MHs.eCA javadoc:
 119                 //    If T0 is a reference and T1 a primitive, and if the reference
 120                 //    is null at runtime, a zero value is introduced.
 121                 for (TestConversionMode mode : TestConversionMode.values()) {
 122                     testConversion(mode, from.wrapperType(),
 123                             to.primitiveType(), null, to.zero(), false, null);
 124                 }
 125             }
 126         }
 127     }
 128 
 129     /**
 130      * Tests that non-null wrapper reference is successfully converted to
 131      * primitive types.
 132      */
 133     public static void testRef2Prim() {
 134         for (Wrapper from : Wrapper.values()) {
 135             for (Wrapper to : Wrapper.values()) {
 136                 if (from == Wrapper.VOID || to == Wrapper.VOID
 137                         || to == Wrapper.OBJECT) {
 138                     continue;
 139                 }
 140                 Object value = RANDOM_VALUES.get(from);
 141                 for (TestConversionMode mode : TestConversionMode.values()) {
 142                     if (from != Wrapper.OBJECT) {
 143                         Object convValue = to.wrap(value);
 144                         testConversion(mode, from.wrapperType(),
 145                                 to.primitiveType(), value, convValue, false, null);
 146                     } else {
 147                         testConversion(mode, from.wrapperType(),
 148                                 to.primitiveType(), value, null,
 149                                 true, ClassCastException.class);
 150                     }
 151                 }
 152             }
 153         }
 154     }
 155 
 156     /**
 157      * Tests that primitive is successfully converted to wrapper reference
 158      * types, to the Number type (if possible) and to the Object type.
 159      */
 160     public static void testPrim2Ref() {
 161         for (Wrapper from : Wrapper.values()) {
 162             for (Wrapper to : Wrapper.values()) {
 163                 if (from == Wrapper.VOID || from == Wrapper.OBJECT
 164                         || to == Wrapper.VOID || to == Wrapper.OBJECT) {
 165                     continue;
 166                 }
 167                 Object value = RANDOM_VALUES.get(from);
 168                 for (TestConversionMode mode : TestConversionMode.values()) {
 169                     if (from == to) {
 170                         testConversion(mode, from.primitiveType(),
 171                                 to.wrapperType(), value, value, false, null);
 172                     } else {
 173                         testConversion(mode, from.primitiveType(),
 174                                 to.wrapperType(), value, null, true, ClassCastException.class);
 175                     }
 176                     if (from != Wrapper.BOOLEAN && from != Wrapper.CHAR) {
 177                         testConversion(mode, from.primitiveType(),
 178                                 Number.class, value, value, false, null);
 179                     } else {
 180                         testConversion(mode, from.primitiveType(),
 181                                 Number.class, value, null,
 182                                 true, ClassCastException.class);
 183                     }
 184                     testConversion(mode, from.primitiveType(),
 185                             Object.class, value, value, false, null);
 186                 }
 187             }
 188         }
 189     }
 190 
 191     /**
 192      * Tests that primitive is successfully converted to other primitive type.
 193      */
 194     public static void testPrim2Prim() {
 195         for (Wrapper from : Wrapper.values()) {
 196             for (Wrapper to : Wrapper.values()) {
 197                 if (from == Wrapper.VOID || to == Wrapper.VOID
 198                         || from == Wrapper.OBJECT || to == Wrapper.OBJECT) {
 199                     continue;
 200                 }
 201                 Object value = RANDOM_VALUES.get(from);
 202                 Object convValue = to.wrap(value);
 203                 for (TestConversionMode mode : TestConversionMode.values()) {
 204                     testConversion(mode, from.primitiveType(),
 205                             to.primitiveType(), value, convValue, false, null);
 206                 }
 207             }
 208         }
 209     }
 210 
 211     /**
 212      * Dummy interface for {@link #testNonBCPRef2Ref} test.
 213      */
 214     public static interface TestInterface {}
 215 
 216     /**
 217      * Dummy class for {@link #testNonBCPRef2Ref} test.
 218      */
 219     public static class TestSuperClass implements TestInterface {}
 220 
 221     /**
 222      * Dummy class for {@link #testNonBCPRef2Ref} test.
 223      */
 224     public static class TestSubClass1 extends TestSuperClass {}
 225 
 226     /**
 227      * Dummy class for {@link #testNonBCPRef2Ref} test.
 228      */
 229     public static class TestSubClass2 extends TestSuperClass {}
 230 
 231     /**
 232      * Tests non-bootclasspath reference to reference conversions.
 233      *
 234      * @throws java.lang.Throwable
 235      */
 236     public static void testNonBCPRef2NonBCPRef() throws Throwable {
 237         Class testInterface = TestInterface.class;
 238         Class testSuperClass = TestSuperClass.class;
 239         Class testSubClass1 = TestSubClass1.class;
 240         Class testSubClass2 = TestSubClass2.class;
 241         Object testSuperObj = new TestSuperClass();
 242         Object testObj01 = new TestSubClass1();
 243         Object testObj02 = new TestSubClass2();
 244         Class[] parents = {testInterface, testSuperClass};
 245         Class[] children = {testSubClass1, testSubClass2};
 246         Object[] childInst = {testObj01, testObj02};
 247         for (TestConversionMode mode : TestConversionMode.values()) {
 248             for (Class parent : parents) {
 249                 for (int j = 0; j < children.length; j++) {
 250                     // Child type to parent type non-null conversion, shoud succeed
 251                     testConversion(mode, children[j], parent, childInst[j], childInst[j], false, null);
 252                     // Child type to parent type null conversion, shoud succeed
 253                     testConversion(mode, children[j], parent, null, null, false, null);
 254                     // Parent type to child type non-null conversion with parent
 255                     // type instance, should fail
 256                     testConversion(mode, parent, children[j], testSuperObj, null, true, ClassCastException.class);
 257                     // Parent type to child type non-null conversion with child
 258                     // type instance, should succeed
 259                     testConversion(mode, parent, children[j], childInst[j], childInst[j], false, null);
 260                     // Parent type to child type null conversion, should succeed
 261                     testConversion(mode, parent, children[j], null, null, false, null);
 262                 }
 263                 // Parent type to child type non-null conversion with sibling
 264                 // type instance, should fail
 265                 testConversion(mode, parent, testSubClass1, testObj02, null, true, ClassCastException.class);
 266             }
 267             // Sibling type non-null conversion, should fail
 268             testConversion(mode, testSubClass1,
 269                     testSubClass2, testObj01, null, true,
 270                     ClassCastException.class);
 271             // Sibling type null conversion, should succeed
 272             testConversion(mode, testSubClass1,
 273                     testSubClass2, null, null, false, null);
 274         }
 275     }
 276 
 277     /**
 278      * Dummy interface for {@link #testNonBCPRef2BCPRef} test.
 279      */
 280     public static interface TestSerializableInterface extends Serializable {}
 281 
 282     /**
 283      * Dummy class for {@link #testNonBCPRef2BCPRef} test.
 284      */
 285     public static class TestSerializableClass
 286             implements TestSerializableInterface {}
 287 
 288     /**
 289      * Dummy class for {@link #testNonBCPRef2BCPRef} test.
 290      */
 291     public static class TestFileChildClass extends File
 292             implements TestSerializableInterface {
 293         public TestFileChildClass(String pathname) {
 294             super(pathname);
 295         }
 296     }
 297 
 298     /**
 299      * Tests non-bootclasspath reference to bootclasspath reference conversions
 300      * and vice-versa.
 301      *
 302      * @throws java.lang.Throwable
 303      */
 304     public static void testNonBCPRef2BCPRef() throws Throwable {
 305         Class bcpInterface = Serializable.class;
 306         Class bcpSuperClass = File.class;
 307         Class nonBcpInterface = TestSerializableInterface.class;
 308         Class nonBcpSuperSiblingClass = TestSerializableClass.class;
 309         Class nonBcpSubClass = TestFileChildClass.class;
 310         Object bcpSuperObj = new File(".");
 311         Object testSuperSiblingObj = new TestSerializableClass();
 312         Object testSubObj = new TestFileChildClass(".");
 313         Class[] parents = {bcpInterface, bcpSuperClass};
 314         for (TestConversionMode mode : TestConversionMode.values()) {
 315             for (Class parent : parents) {
 316                 // Child type to parent type non-null conversion, shoud succeed
 317                 testConversion(mode, nonBcpSubClass, parent, testSubObj,
 318                         testSubObj, false, null);
 319                 // Child type to parent type null conversion, shoud succeed
 320                 testConversion(mode, nonBcpSubClass, parent, null, null,
 321                         false, null);
 322                 // Parent type to child type non-null conversion with parent
 323                 // type instance, should fail
 324                 testConversion(mode, parent, nonBcpSubClass, bcpSuperObj, null,
 325                         true, ClassCastException.class);
 326                 // Parent type to child type non-null conversion with child
 327                 // type instance, should succeed
 328                 testConversion(mode, parent, nonBcpSubClass, testSubObj,
 329                         testSubObj, false, null);
 330                 // Parent type to child type null conversion, should succeed
 331                 testConversion(mode, parent, nonBcpSubClass, null, null,
 332                         false, null);
 333             }
 334             // Parent type to child type non-null conversion with
 335             // super sibling type instance, should fail
 336             testConversion(mode, bcpInterface, nonBcpSubClass,
 337                     testSuperSiblingObj, null, true, ClassCastException.class);
 338             Class[] siblings = {nonBcpSubClass, bcpSuperClass};
 339             for (Class sibling : siblings) {
 340                 // Non-bcp class to bcp/non-bcp sibling class non-null
 341                 // conversion with nonBcpSuperSiblingClass instance, should fail
 342                 testConversion(mode, nonBcpSuperSiblingClass, sibling,
 343                         testSuperSiblingObj, null, true, ClassCastException.class);
 344                 // Non-bcp class to bcp/non-bcp sibling class null conversion,
 345                 // should succeed
 346                 testConversion(mode, nonBcpSuperSiblingClass, sibling,
 347                         null, null, false, null);
 348                 // Non-bcp interface to bcp/non-bcp sibling class non-null
 349                 // conversion with nonBcpSubClass instance, should succeed
 350                 testConversion(mode, nonBcpInterface, sibling, testSubObj,
 351                         testSubObj, false, null);
 352                 // Non-bcp interface to bcp/non-bcp sibling class
 353                 // null conversion, should succeed
 354                 testConversion(mode, nonBcpInterface, sibling, null, null,
 355                         false, null);
 356                 // Non-bcp interface to bcp/non-bcp sibling class non-null
 357                 // conversion with nonBcpSuperSiblingClass instance, should fail
 358                 testConversion(mode, nonBcpInterface, sibling,
 359                         testSuperSiblingObj, testSubObj,
 360                         true, ClassCastException.class);
 361             }
 362         }
 363     }
 364 
 365     /**
 366      * Tests bootclasspath reference to reference conversions.
 367      */
 368     public static void testBCPRef2BCPRef() {
 369         Class bcpInterface = CharSequence.class;
 370         Class bcpSubClass1 = String.class;
 371         Class bcpSubClass2 = StringBuffer.class;
 372         Object testObj01 = new String("test");
 373         Object testObj02 = new StringBuffer("test");
 374         Class[] children = {bcpSubClass1, bcpSubClass2};
 375         Object[] childInst = {testObj01, testObj02};
 376         for (TestConversionMode mode : TestConversionMode.values()) {
 377             for (int i = 0; i < children.length; i++) {
 378                 // Child type to parent type non-null conversion, shoud succeed
 379                 testConversion(mode, children[i], bcpInterface, childInst[i],
 380                         childInst[i], false, null);
 381                 // Child type to parent type null conversion, shoud succeed
 382                 testConversion(mode, children[i], bcpInterface, null,
 383                         null, false, null);
 384                 // Parent type to child type non-null conversion with child
 385                 // type instance, should succeed
 386                 testConversion(mode, bcpInterface,
 387                         children[i], childInst[i], childInst[i], false, null);
 388                 // Parent type to child type null conversion, should succeed
 389                 testConversion(mode, bcpInterface,
 390                         children[i], null, null, false, null);
 391             }
 392             // Sibling type non-null conversion, should fail
 393             testConversion(mode, bcpSubClass1,
 394                     bcpSubClass2, testObj01, null, true,
 395                     ClassCastException.class);
 396             // Sibling type null conversion, should succeed
 397             testConversion(mode, bcpSubClass1,
 398                     bcpSubClass2, null, null, false, null);
 399             // Parent type to child type non-null conversion with sibling
 400             // type instance, should fail
 401             testConversion(mode, bcpInterface, bcpSubClass1, testObj02,
 402                     null, true, ClassCastException.class);
 403         }
 404     }
 405 
 406     /**
 407      * Dummy method used in {@link #testReturnAny2Void} and
 408      * {@link #testReturnVoid2Any} tests to form a method handle.
 409      */
 410     public static void retVoid() {}
 411 
 412     /**
 413      * Tests that non-null any return is successfully converted to non-type
 414      * void.
 415      */
 416     public static void testReturnAny2Void() {
 417         for (Wrapper from : Wrapper.values()) {
 418             testConversion(TestConversionMode.RETURN_VALUE, from.wrapperType(),
 419                     void.class, RANDOM_VALUES.get(from),
 420                     null, false, null);
 421             testConversion(TestConversionMode.RETURN_VALUE, from.primitiveType(),
 422                     void.class, RANDOM_VALUES.get(from),
 423                     null, false, null);
 424         }
 425     }
 426 
 427     /**
 428      * Tests that void return is successfully converted to primitive and
 429      * reference. Result should be zero for primitives and null for references.
 430      */
 431     public static void testReturnVoid2Any() {
 432         for (Wrapper to : Wrapper.values()) {
 433             testConversion(TestConversionMode.RETURN_VALUE, void.class,
 434                     to.primitiveType(), null,
 435                     to.zero(), false, null);
 436             testConversion(TestConversionMode.RETURN_VALUE, void.class,
 437                     to.wrapperType(), null,
 438                     null, false, null);
 439         }
 440     }
 441 
 442     private static void checkForWrongMethodTypeException(MethodHandle mh, MethodType mt) {
 443         try {
 444             MethodHandles.explicitCastArguments(mh, mt);
 445             throw new AssertionError("Expected WrongMethodTypeException is not thrown");
 446         } catch (WrongMethodTypeException wmte) {
 447             if (VERBOSE) {
 448                 System.out.printf("Expected exception %s: %s\n",
 449                         wmte.getClass(), wmte.getMessage());
 450             }
 451         }
 452     }
 453 
 454     /**
 455      * Tests that MHs.eCA method works correctly with MHs with multiple arguments.
 456      * @throws Throwable
 457      */
 458     public static void testMultipleArgs() throws Throwable {
 459         int arity = 1 + RNG.nextInt(Helper.MAX_ARITY / 2 - 2);
 460         int arityMinus = RNG.nextInt(arity);
 461         int arityPlus = arity + RNG.nextInt(Helper.MAX_ARITY / 2 - arity) + 1;
 462         MethodType mType = Helper.randomMethodTypeGenerator(arity);
 463         MethodType mTypeNew = Helper.randomMethodTypeGenerator(arity);
 464         MethodType mTypeNewMinus = Helper.randomMethodTypeGenerator(arityMinus);
 465         MethodType mTypeNewPlus = Helper.randomMethodTypeGenerator(arityPlus);
 466         Class<?> rType = mType.returnType();
 467         MethodHandle original;
 468         if (rType.equals(void.class)) {
 469             MethodType mt = MethodType.methodType(void.class);
 470             original = MethodHandles.publicLookup()
 471                     .findStatic(THIS_CLASS, "retVoid", mt);
 472         } else {
 473             Object rValue = Helper.castToWrapper(1, rType);
 474             original = MethodHandles.constant(rType, rValue);
 475         }
 476         original = Helper.addTrailingArgs(original, arity, mType.parameterList());
 477         MethodHandle target = MethodHandles
 478                     .explicitCastArguments(original, mTypeNew);
 479         Object[] parList = Helper.randomArgs(mTypeNew.parameterList());
 480         for (int i = 0; i < parList.length; i++) {
 481             if (parList[i] instanceof String) {
 482                 parList[i] = null; //getting rid of Stings produced by randomArgs
 483             }
 484         }
 485         target.invokeWithArguments(parList);
 486         checkForWrongMethodTypeException(original, mTypeNewMinus);
 487         checkForWrongMethodTypeException(original, mTypeNewPlus);
 488     }
 489 
 490     /**
 491      * Enumeration of test conversion modes.
 492      */
 493     public enum TestConversionMode {
 494         RETURN_VALUE,
 495         ARGUMENT;
 496     }
 497 
 498     /**
 499      * Tests type and value conversion. Comparing with the given expected result.
 500      *
 501      * @param mode - test conversion mode. See {@link #TestConversionMode}.
 502      * @param from - source type.
 503      * @param to - destination type.
 504      * @param param - value to be converted.
 505      * @param expectedResult - expected value after conversion.
 506      * @param failureExpected - true if conversion failure expected.
 507      * @param expectedException - expected exception class if
 508      * {@code failureExpected} is true.
 509      */
 510     public static void testConversion(TestConversionMode mode,
 511             Class<?> from, Class<?> to, Object param,
 512             Object expectedResult, boolean failureExpected,
 513             Class<? extends Throwable> expectedException) {
 514         if (VERBOSE) {
 515             System.out.printf("Testing return value conversion: "
 516                     + "%-10s => %-10s: %5s: ", from.getSimpleName(),
 517                     to.getSimpleName(), param);
 518         }
 519         MethodHandle original = null;
 520         MethodType newType = null;
 521         switch (mode) {
 522             case RETURN_VALUE:
 523                 if (from.equals(void.class)) {
 524                     MethodType mt = MethodType.methodType(void.class);
 525                     try {
 526                         original = MethodHandles.publicLookup()
 527                                 .findStatic(THIS_CLASS, "retVoid", mt);
 528                     } catch (NoSuchMethodException | IllegalAccessException ex) {
 529                         throw new Error("Unexpected issue", ex);
 530                     }
 531                 } else {
 532                     original = MethodHandles.constant(from, param);
 533                 }
 534                 newType = original.type().changeReturnType(to);
 535                 break;
 536             case ARGUMENT:
 537                 if (from.equals(void.class) || to.equals(void.class)) {
 538                     throw new Error("Test issue: argument conversion does not"
 539                             + " work with non-type void");
 540                 }
 541                 original = MethodHandles.identity(to);
 542                 newType = original.type().changeParameterType(0, from);
 543                 break;
 544             default:
 545                 String msg = String.format("Test issue: unknown test"
 546                         + " convertion mode %s.", mode.name());
 547                 throw new Error(msg);
 548         }
 549         try {
 550             MethodHandle target = MethodHandles
 551                     .explicitCastArguments(original, newType);
 552             Object result;
 553             switch (mode) {
 554                 case RETURN_VALUE:
 555                     result = target.invokeWithArguments();
 556                     break;
 557                 case ARGUMENT:
 558                     result = target.invokeWithArguments(param);
 559                     break;
 560                 default:
 561                     String msg = String.format("Test issue: unknown test"
 562                             + " convertion mode %s.", mode.name());
 563                     throw new Error(msg);
 564             }
 565             if (!failureExpected
 566                     && (expectedResult != null && !expectedResult.equals(result)
 567                     || expectedResult == null && result != null)) {
 568                 String msg = String.format("Conversion result %s is not equal"
 569                         + " to the expected result %10s",
 570                         result, expectedResult);
 571                 throw new AssertionError(msg);
 572             }
 573             if (VERBOSE) {
 574                 String resultStr;
 575                 if (result != null) {
 576                     resultStr = String.format("Converted value and type are"
 577                             + " %10s (%10s)", "'" + result + "'",
 578                             result.getClass().getSimpleName());
 579                 } else {
 580                     resultStr = String.format("Converted value is %10s", result);
 581                 }
 582                 System.out.println(resultStr);
 583             }

 584             if (failureExpected) {
 585                 String msg = String.format("No exception thrown while testing"
 586                         + " return value conversion: %10s => %10s;"
 587                         + " parameter: %10s",
 588                         from, to, param);
 589                 throw new AssertionError(msg);
 590             }
 591         } catch (AssertionError e) {
 592             throw e; // report test failure
 593         } catch (Throwable e) {
 594             if (VERBOSE) {
 595                 System.out.printf("%s: %s\n", e.getClass(), e.getMessage());
 596             }
 597             if (!failureExpected || !e.getClass().equals(expectedException)) {
 598                 String msg = String.format("Unexpected exception was thrown"
 599                         + " while testing return value conversion:"
 600                         + " %s => %s; parameter: %s", from, to, param);
 601                 throw new AssertionError(msg, e);
 602             }
 603         }
 604     }
 605 }
< prev index next >