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