/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/* @test
* @summary unit tests for java.lang.invoke.MethodHandles
* @compile MethodHandlesTest.java remote/RemoteExample.java
*/
/**
*
* @author jrose
*/
public class MethodHandlesTest {
// How much output?
static {
}
// Set this true during development if you want to fast-forward to
// a particular new, non-working test. Tests which are known to
// work (or have recently worked) test this flag and return on true.
static final boolean CAN_SKIP_WORKING;
static {
}
// Set 'true' to do about 15x fewer tests, especially those redundant with RicochetTest.
// This might be useful with -Xcomp stress tests that compile all method handles.
@Test
verbosity += 9; try {
// left blank for debugging
}
public MethodHandlesTest() {
}
public void printCounts() {
allPosTests += posTests;
allNegTests += negTests;
}
}
else ++negTests;
}
if (verbosity >= 1)
}
}
}
}
}
return entry;
}
}
if (verbosity >= 3)
}
}
return (int)(value);
return (long)(value);
return (char)(value);
return (short)(value);
return (float)(value);
return (double)(value);
return (byte)(value);
return null;
}
static long nextArgVal;
long val = nextArgVal++;
val >>= 1;
if (moreBits)
// Guarantee some bits in the high word.
// In any case keep the decimal representation simple-looking,
// with lots of zeroes, so as not to make the printed decimal
// strings unnecessarily noisy.
}
static int nextArg() {
// Produce a 32-bit result something like ONE_MILLION+(smallint).
// Example: 1_000_042.
return (int) nextArg(false);
}
// produce a 64-bit result something like
// ((TEN_BILLION+1) * (ONE_MILLION+(smallint)))
// Example: 10_000_420_001_000_042.
return nextArg(true);
return (long) nextArg();
}
return wrap;
}
// import sun.invoke.util.Wrapper;
// Wrapper wrap = Wrapper.forBasicType(dst);
// if (wrap == Wrapper.OBJECT && Wrapper.isWrapperType(dst))
// wrap = Wrapper.forWrapperType(dst);
// if (wrap != Wrapper.OBJECT)
// return wrap.wrap(nextArg++);
if (param.isInterface()) {
{ param = c; break; }
}
}
return "#"+nextArg();
else
try {
return param.newInstance();
}
return null; // random class not Object, String, Integer, etc.
}
return args;
}
return args;
}
}
static <T> T[] cat(T[] a, T... b) {
if (blen == 0) return a;
return c;
}
}
return res;
}
if (x == null) return x;
if (x instanceof String) return x; // keep the name
if (x instanceof List) {
// recursively report classes of the list elements
}
return x.getClass().getSimpleName();
}
/** Return lambda(arg...[arity]) { new Object[]{ arg... } } */
}
/** Return lambda(arg...[arity]) { Arrays.asList(arg...) } */
}
}
/** Variation of varargsList, but with the given rtype. */
// OK
if (LIST_TO_STRING == null)
try {
} else if (rtype.isPrimitive()) {
if (LIST_TO_INT == null)
try {
} else {
}
}
}
}
}
// This lookup is good for all members in and under MethodHandlesTest.
// This lookup is good for package-private members but not private ones.
// This lookup is good for public members and protected members of PubExample
// This lookup is good only for public members.
// Subject methods...
@SuppressWarnings("LeakingThisInConstructor")
// for testing findConstructor:
public Example(int x, int y, int z, int a) { this.name = x+""+y+""+z+""+a; called("Example.<init>", x, y, z, a); }
}
}
@SuppressWarnings("LeakingThisInConstructor")
}
public static interface IntExample {
public void v0();
}
}
{ { false, PUBLIC }, { false, SUBCLASS }, { false, PACKAGE }, { false, PRIVATE }, { false, EXAMPLE } }, //[0]: all false
{ { false, PUBLIC }, { false, SUBCLASS }, { false, PACKAGE }, { true, PRIVATE }, { true, EXAMPLE } }, //[1]: only PRIVATE
{ { false, PUBLIC }, { false, SUBCLASS }, { true, PACKAGE }, { true, PRIVATE }, { true, EXAMPLE } }, //[2]: PUBLIC false
{ { false, PUBLIC }, { true, SUBCLASS }, { true, PACKAGE }, { true, PRIVATE }, { true, EXAMPLE } }, //[3]: subclass OK
{ { true, PUBLIC }, { true, SUBCLASS }, { true, PACKAGE }, { true, PRIVATE }, { true, EXAMPLE } }, //[4]: all true
};
} else {
if (pubc)
else
}
return cases;
}
}
// external views stay external
return lookup;
}
@Test
if (CAN_SKIP_WORKING) return;
startTest("findStatic");
}
void testFindStatic(Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable {
}
}
void testFindStatic(Lookup lookup, Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable {
}
void testFindStatic(boolean positive, Lookup lookup, Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable {
try {
} catch (ReflectiveOperationException ex) {
else
}
if (verbosity >= 3)
assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null);
if (!positive) return; // negative test failed as expected
if (verbosity >= 1)
}
static final boolean DEBUG_METHOD_HANDLE_NAMES = Boolean.getBoolean("java.lang.invoke.MethodHandle.DEBUG_NAMES");
// rough check of name string
if (!DEBUG_METHOD_HANDLE_NAMES) {
// ignore s
return;
}
assertEquals(s, x);
}
@Test
if (CAN_SKIP_WORKING) return;
startTest("findVirtual");
// test dispatch
}
void testFindVirtual(Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable {
}
void testFindVirtual(Class<?> rcvc, Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable {
}
}
void testFindVirtual(Lookup lookup, Class<?> rcvc, Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable {
}
void testFindVirtual(boolean positive, Lookup lookup, Class<?> rcvc, Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable {
try {
} catch (ReflectiveOperationException ex) {
else
}
if (verbosity >= 3)
assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null);
if (!positive) return; // negative test failed as expected
// predict receiver type narrowing:
}
if (verbosity >= 1)
}
@Test
if (CAN_SKIP_WORKING) return;
startTest("findSpecial");
// Do some negative testing:
}
}
if (specialCaller == RemoteExample.class) {
return;
}
}
try {
} catch (ReflectiveOperationException ex) {
else
}
if (verbosity >= 3)
System.out.println("findSpecial from "+specialCaller.getName()+" to "+defc.getName()+"."+name+"/"+type+" => "+target
assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null);
if (!positive) return; // negative test failed as expected
}
@Test
if (CAN_SKIP_WORKING) return;
startTest("findConstructor");
}
try {
} catch (ReflectiveOperationException ex) {
}
if (verbosity >= 3)
assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null);
if (!positive) return; // negative test failed as expected
}
@Test
if (CAN_SKIP_WORKING) return;
startTest("bind");
}
}
}
void testBind(boolean positive, Lookup lookup, Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable {
try {
} catch (ReflectiveOperationException ex) {
else
}
if (verbosity >= 3)
assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null);
if (!positive) return; // negative test failed as expected
if (verbosity >= 1)
}
@Test
if (CAN_SKIP_WORKING) return;
startTest("unreflect");
// Test a public final member in another package:
}
void testUnreflect(Class<?> defc, boolean isStatic, Class<?> ret, String name, Class<?>... params) throws Throwable {
testUnreflectMaybeSpecial(null, (Boolean)ac[0], (Lookup)ac[1], defc, (isStatic ? null : defc), ret, name, params);
}
}
void testUnreflect(Class<?> defc, Class<?> rcvc, Class<?> ret, String name, Class<?>... params) throws Throwable {
}
}
try {
if (isSpecial)
else
} catch (ReflectiveOperationException ex) {
else
}
if (verbosity >= 3)
+" => "+target
assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null);
if (!positive) return; // negative test failed as expected
if (!isStatic) {
}
if (isStatic) {
} else {
if (isSpecial)
else
}
if (verbosity >= 1)
}
void testUnreflectSpecial(Class<?> defc, Class<?> rcvc, Class<?> ret, String name, Class<?>... params) throws Throwable {
testUnreflectMaybeSpecial(specialCaller, (Boolean)ac[0], (Lookup)ac[1], defc, rcvc, ret, name, params);
}
}
@Test
if (CAN_SKIP_WORKING) return;
startTest("unreflectSpecial");
testUnreflectMaybeSpecial(Example.class, false, PRIVATE, Example.class, Example.class, void.class, "s0");
}
public static class HasFields {
boolean fZ = false;
static boolean sZ = true;
static {
{'I',int.class}, {'J',long.class},
{'F',float.class}, {'D',double.class},
{'Z',boolean.class}, {'B',byte.class},
{'S',short.class}, {'C',char.class},
};
try {
}
try {
}
if (type == float.class) {
float v = 'F';
if (isStatic) v++;
}
}
}
cases.add(new Object[]{ new Object[]{ false, HasFields.class, "bogus_fD", double.class }, Error.class });
cases.add(new Object[]{ new Object[]{ true, HasFields.class, "bogus_sL", Object.class }, Error.class });
}
}
static final int TEST_UNREFLECT = 1, TEST_FIND_FIELD = 2, TEST_FIND_STATIC = 3, TEST_SETTER = 0x10, TEST_BOUND = 0x20, TEST_NPE = 0x40;
switch (testMode) {
case TEST_FIND_STATIC: return isStatic;
case TEST_FIND_FIELD: return !isStatic;
case TEST_UNREFLECT: return true; // unreflect matches both
}
}
@Test
if (CAN_SKIP_WORKING) return;
startTest("unreflectGetter");
}
@Test
if (CAN_SKIP_WORKING) return;
startTest("findGetter");
}
@Test
if (CAN_SKIP_WORKING) return;
startTest("findStaticGetter");
}
if (positive)
}
testGetter(true, lookup,
testGetter(false, lookup,
}
}
}
if (verbosity >= 4)
System.out.println("testAccessor"+Arrays.deepToString(new Object[]{positive0, lookup, fieldRef, value, testMode0}));
boolean isStatic;
if (f != null) {
fclass = f.getDeclaringClass();
} else {
try {
} catch (ReflectiveOperationException ex) {
f = null;
}
}
if (isGetter)
else
try {
case TEST_SETTER|
case TEST_SETTER|
case TEST_SETTER|
default:
}
} catch (ReflectiveOperationException ex) {
else
}
if (verbosity >= 3)
System.out.println("find"+(isStatic?"Static":"")+(isGetter?"Getter":"Setter")+" "+fclass.getName()+"."+fname+"/"+ftype
+" => "+mh
assertEquals(positive0 ? "positive test" : "negative test erroneously passed", positive0, mh != null);
//assertNameStringContains(mh, fname); // This does not hold anymore with LFs
if (doBound)
if (isGetter) {
} else {
.changeReturnType(void.class)
}
}
if (isGetter) {
for (int i = 0; i <= 1; i++) {
try {
if (ftype == int.class)
else
} else {
if (ftype == int.class)
else
}
} catch (RuntimeException ex) {
break;
}
}
} else {
break;
}
}
} else {
for (int i = 0; i <= 1; i++) {
try {
if (ftype == int.class)
else
} else {
if (ftype == int.class)
else
}
} catch (RuntimeException ex) {
break;
}
}
}
}
}
}
if (testNPE) {
throw new RuntimeException("failed to catch NPE exception"+(caughtEx == null ? " (caughtEx=null)" : ""), caughtEx);
}
}
}
@Test
if (CAN_SKIP_WORKING) return;
startTest("unreflectSetter");
}
@Test
if (CAN_SKIP_WORKING) return;
startTest("findSetter");
}
@Test
if (CAN_SKIP_WORKING) return;
startTest("findStaticSetter");
}
startTest("unreflectSetter");
if (positive)
}
testSetter(false, lookup,
}
}
}
@Test
if (CAN_SKIP_WORKING) return;
startTest("arrayElementGetter");
testArrayElementGetterSetter(false);
}
@Test
if (CAN_SKIP_WORKING) return;
startTest("arrayElementSetter");
testArrayElementGetterSetter(true);
}
private static final int TEST_ARRAY_NONE = 0, TEST_ARRAY_NPE = 1, TEST_ARRAY_OOB = 2, TEST_ARRAY_ASE = 3;
}
@Test
if (CAN_SKIP_WORKING) return;
startTest("arrayElementErrors");
}
}
public void testArrayElementGetterSetter(Object array, boolean testSetter, int negTest) throws Throwable {
// this stanza allows negative tests to make argument perturbations:
switch (negTest) {
case TEST_ARRAY_NPE:
break;
case TEST_ARRAY_OOB:
assert(length > 0);
break;
case TEST_ARRAY_ASE:
else if (elemType == IntExample.class)
else
return; // can't make an ArrayStoreException test
break;
}
if (verbosity > 2) System.out.println("array type = "+array.getClass().getComponentType().getName()+"["+length+"]"+(positive ? "" : " negative test #"+negTest+" using "+Arrays.deepToString(new Object[]{arrayToMH})));
}
for (int i = 0; i < length; i++) {
// update array element
if (testSetter) {
try {
if (elemType == int.class)
else if (elemType == boolean.class)
else
} catch (RuntimeException ex) {
break;
}
} else {
}
if (verbosity >= 5) {
}
// observe array element
if (!testSetter) {
try {
if (elemType == int.class)
else if (elemType == boolean.class)
else
} catch (RuntimeException ex) {
break;
}
}
}
if (!positive) {
// test the kind of exception
switch (negTest) {
default: assert(false);
}
}
}
}
}
for (int i = 0; i < length; i++)
return model;
}
static class Callee {
}
if (n == -1)
}
}
try {
throw new RuntimeException(ex);
}
}
}
@Test
if (CAN_SKIP_WORKING) return;
startTest("convertArguments");
}
void testConvert(MethodHandle id, Class<?> rtype, String name, Class<?>... params) throws Throwable {
}
}
// simulate the pairwise conversion
}
{
}
try {
} catch (WrongMethodTypeException ex) {
}
if (verbosity >= 3)
assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null);
if (!positive) return; // negative test failed as expected
if (verbosity >= 1)
}
@Test
if (CAN_SKIP_WORKING) return;
startTest("varargsCollector");
}
}
@Test // SLOW
if (CAN_SKIP_WORKING) return;
startTest("permuteArguments");
if (CAN_TEST_LIGHTLY) return;
}
public void testPermuteArguments(int max, Class<?> type1, int t2c, Class<?> type2, int dilution) throws Throwable {
if (verbosity >= 2)
if (t2c != 0) {
// Fill in a middle range with type2:
}
int numcases = 1;
// Avoid some common factors:
casStep++;
if (CAN_TEST_LIGHTLY) continue;
// Do some special patterns, which we probably missed.
// Replication of a single argument or argument pair.
for (int i = 0; i < inargs; i++) {
for (int d = 1; d <= 2; d++) {
if (i + d >= inargs) continue;
reorder[j] += 1;
}
}
// Repetition of a sequence of 3 or more arguments.
for (int i = 1; i < inargs; i++) {
for (int j = 0; j < outargs; j++)
}
}
}
}
}
}
c /= inargs;
}
if (CAN_TEST_LIGHTLY && outargs >= 3 && (reorder[0] == reorder[1] || reorder[1] == reorder[2])) continue;
}
}
}
return reorder;
}
countTest();
int max = 0;
for (int j : reorder) {
}
}
}
}
if (verbosity >= 3)
for (int i = 0; i < outargs; i++) {
}
if (verbosity >= 4) {
}
System.out.println("*** failed permuteArguments "+Arrays.toString(reorder)+" types="+Arrays.asList(types));
}
}
@Test // SLOW
if (CAN_SKIP_WORKING) return;
startTest("spreadArguments");
if (verbosity >= 3)
continue;
}
}
}
}
countTest();
if (verbosity >= 3)
// make sure the target does what we think it does:
switch (nargs) {
case 0:
break;
case 1:
break;
case 2:
break;
}
}
{ // modify newParams in place
}
if (pos == 0) {
Object args2 = ValueConversions.changeArrayType(arrayType, Arrays.copyOfRange(args, pos, args.length));
} else {
args1[pos] = ValueConversions.changeArrayType(arrayType, Arrays.copyOfRange(args, pos, args.length));
}
if (!argType.isPrimitive()) {
}
} else if (argType == int.class) {
}
} else if (argType == long.class) {
}
} else {
// cannot test...
}
}
@Test // SLOW
if (CAN_SKIP_WORKING) return;
startTest("collectArguments");
if (verbosity >= 3)
continue;
}
}
}
}
countTest();
// fake up a MH with the same type as the desired adapter:
// here is what should happen:
// here is the MH which will witness the collected argument tail:
if (verbosity >= 3)
// assertTrue(returnValue.length == pos+1 && returnValue[pos] instanceof Object[]);
// returnValue[pos] = Arrays.asList((Object[]) returnValue[pos]);
// collectedArgs[pos] = Arrays.asList((Object[]) collectedArgs[pos]);
}
@Test // SLOW
if (CAN_SKIP_WORKING) return;
startTest("insertArguments");
continue;
continue;
}
}
}
}
countTest();
if (verbosity >= 3)
if (verbosity >= 3)
//if (!resList.equals(res2List))
// System.out.println("*** fail at n/p/i = "+nargs+"/"+pos+"/"+ins+": "+resList+" => "+res2List);
}
@Test
if (CAN_SKIP_WORKING) return;
startTest("filterReturnValue");
List.class,
int.class,
byte.class,
long.class,
CharSequence.class,
String.class }) {
}
}
}
countTest();
else
if (verbosity >= 3)
if (verbosity >= 4)
// Simulate expected effect of filter on return value:
if (verbosity >= 4)
if (verbosity >= 4)
if (verbosity >= 3)
System.out.println("*** fail at n/rt = "+nargs+"/"+rtype.getSimpleName()+": "+Arrays.asList(argsToPass)+" => "+result+" != "+expected);
}
@Test
if (CAN_SKIP_WORKING) return;
startTest("filterArguments");
}
}
}
countTest();
if (verbosity >= 3)
// Simulate expected effect of filter on arglist:
if (verbosity >= 3)
System.out.println("*** fail at n/p = "+nargs+"/"+pos+": "+Arrays.asList(argsToPass)+" => "+result+" != "+expected);
}
@Test
if (CAN_SKIP_WORKING) return;
startTest("foldArguments");
}
}
}
}
countTest();
if (verbosity >= 3)
// Simulate expected effect of combiner on arglist:
if (verbosity >= 3)
if (verbosity >= 3)
System.out.println("*** fail at n/p/f = "+nargs+"/"+pos+"/"+fold+": "+argsToPass+" => "+result+" != "+expected);
}
@Test
if (CAN_SKIP_WORKING) return;
startTest("dropArguments");
}
}
}
}
countTest();
for (int i = drop; i > 0; i--) {
}
//if (!resList.equals(res2List))
// System.out.println("*** fail at n/p/d = "+nargs+"/"+pos+"/"+drop+": "+argsToDrop+" => "+res2List);
}
@Test // SLOW
if (CAN_SKIP_WORKING) return;
startTest("exactInvoker, genericInvoker, varargsInvoker, dynamicInvoker");
// exactInvoker, genericInvoker, varargsInvoker[0..N], dynamicInvoker
for (int i = 0; i <= 6; i++) {
if (CAN_TEST_LIGHTLY && i > 3) break;
for (int j = -1; j < i; j++) {
if (j < 0)
else if (argType == void.class)
continue;
else
}
}
}
}
if (verbosity >= 3)
// exact invoker
countTest();
// generic invoker
countTest();
switch (nargs) {
case 0:
break;
case 1:
break;
case 2:
break;
case 3:
break;
}
}
// varargs invoker #0
} else if (type.returnType() == void.class) {
} else {
}
// varargs invoker #1
}
// varargs invoker #2
}
// varargs invoker #3
}
for (int k = 0; k <= nargs; k++) {
// varargs invoker #0..N
countTest();
.appendParameterTypes(Object[].class)
}
// dynamic invoker
countTest();
// see if we get the result of the original target:
try {
assertTrue("should not reach here", false);
} catch (IllegalStateException ex) {
}
// set new target after invoker is created, to make sure we track target
}
}
return called("targetIfEquals");
}
return called("fallbackIfNotEquals");
}
assertEquals(x, MISSING_ARG);
return called("targetIfEquals", x);
}
return called("fallbackIfNotEquals", x);
}
assertEquals(x, y);
return called("targetIfEquals", x, y);
}
return called("fallbackIfNotEquals", x, y);
}
assertEquals(x, y);
return called("targetIfEquals", x, y, z);
}
return called("fallbackIfNotEquals", x, y, z);
}
@Test
if (CAN_SKIP_WORKING) return;
startTest("guardWithTest");
}
}
}
}
countTest();
MethodHandle test = PRIVATE.findVirtual(Object.class, "equals", MethodType.methodType(boolean.class, Object.class));
MethodHandle target = PRIVATE.findStatic(MethodHandlesTest.class, "targetIfEquals", MethodType.genericMethodType(nargs1));
MethodHandle fallback = PRIVATE.findStatic(MethodHandlesTest.class, "fallbackIfNotEquals", MethodType.genericMethodType(nargs1));
// 0: test = constant(MISSING_ARG.equals(MISSING_ARG))
// 1: test = lambda (_) MISSING_ARG.equals(_)
}
assert(testArgs >= 0);
{ },
{ "foo" }, { MISSING_ARG },
{ "foo", "foo" }, { "foo", "bar" },
{ "foo", "foo", "baz" }, { "foo", "bar", "baz" }
};
}
}
boolean equals;
switch (nargs) {
case 0: equals = true; break;
}
if (verbosity >= 3)
}
}
@Test
if (CAN_SKIP_WORKING) return;
startTest("catchException");
}
}
}
static final int THROW_NOTHING = 0, THROW_CAUGHT = 1, THROW_UNCAUGHT = 2, THROW_THROUGH_ADAPTER = 3, THROW_MODE_LIMIT = 4;
void testCatchException(Class<?> returnType, Throwable thrown, int throwMode, int nargs) throws Throwable {
}
}
private static <T extends Throwable>
throw exception;
}
return normal;
}
private int fakeIdentityCount;
return x;
}
void testCatchException(Class<?> returnType, Throwable thrown, int throwMode, int nargs, int catchDrops) throws Throwable {
countTest();
if (verbosity >= 3)
System.out.println("catchException rt="+returnType+" throw="+throwMode+" nargs="+nargs+" drops="+catchDrops);
if (throwMode == THROW_THROUGH_ADAPTER) {
for (int i = 0; i < 10; i++)
}
}
//System.out.println("catching with "+target+" : "+throwOrReturn);
try {
if (throwMode <= THROW_CAUGHT)
}
//System.out.println("return from "+target+" : "+returned);
if (throwMode == THROW_NOTHING) {
} else if (throwMode == THROW_CAUGHT) {
// catcher receives an initial subsequence of target arguments:
// catcher also receives the exception, prepended:
}
}
@Test
if (CAN_SKIP_WORKING) return;
startTest("throwException");
}
countTest();
//System.out.println("throwing with "+target+" : "+thrown);
try {
}
}
}
@Test
//if (CAN_SKIP_WORKING) return;
startTest("interfaceCast");
}) {
}) {
// doret docast
}
}
}
return (c.isInterface() ? Object.class : c);
}
if (verbosity > 1)
// this bit is needed to make the interface types disappear for invokeWithArguments:
};
// where might a checkCast occur?
// the string value must pass each step without causing an exception
if (!docast) {
if (!doret) {
} else {
}
}
boolean expectFail = false;
if (!c.isInstance(normalRetVal)) {
if (verbosity > 3)
System.out.println("expect failure at step "+i+" in "+Arrays.toString(step)+Arrays.toString(checkCast));
expectFail = true;
break;
}
}
if (verbosity > 2)
try {
}
if (sawFail != expectFail) {
System.out.println(" retype using "+(docast ? "explicitCastArguments" : "asType")+" to "+mt+" => "+mh);
}
if (!expectFail) {
} else {
}
}
@Test // SLOW
if (CAN_SKIP_WORKING) return;
startTest("testCastFailure");
if (CAN_TEST_LIGHTLY) return;
}
static class Surprise {
}
trace("value", x);
return x;
}
}
static {
try {
Surprise.class, "value",
Surprise.class, "refIdentity",
Surprise.class, "boxIdentity",
Surprise.class, "intIdentity",
MethodType.methodType(int.class, int.class));
throw new RuntimeException(ex);
}
}
}
@SuppressWarnings("ConvertToStringSwitch")
countTest(false);
MethodHandle identity = Surprise.REF_IDENTITY, surprise0 = boo.asMethodHandle(), surprise = surprise0;
// fail on return to ((Integer)surprise).intValue
// fail on return to (Integer)surprise
}
// fail on handing surprise to int argument
// fail on handing surprise to Integer argument
}
}
}
Object x = 42;
for (int i = 0; i < okCount; i++) {
assertEquals(x, y);
assertEquals(x, z);
}
assertEquals(x, y);
try {
assertTrue(false);
} catch (ClassCastException ex) {
if (verbosity > 2)
if (verbosity > 3)
assertTrue(true); // all is well
}
}
called("userMethod", o, s, i);
return null;
}
@Test
if (CAN_SKIP_WORKING) return;
startTest("testUserClassInSignature");
// Try a static method.
name = "userMethod";
// Try a virtual method.
name = "v2";
}
static void runForRunnable() {
called("runForRunnable");
}
public interface Fooable {
// overloads:
}
return called("fooForFooable/"+x, y);
}
}
public interface WillThrow {
}
public void run();
}
@Test
if (CAN_SKIP_WORKING) return;
startTest("asInterfaceInstance");
// test typical case: Runnable.run
{
countTest();
assertCalled("runForRunnable");
}
// well known single-name overloaded interface: Appendable.append
{
countTest();
MethodHandle append = lookup.bind(appendResults, "add", MethodType.methodType(boolean.class, Object.class));
MethodHandle asList = lookup.findStatic(Arrays.class, "asList", MethodType.methodType(List.class, Object[].class));
MethodHandle mh = MethodHandles.filterReturnValue(asList, append).asVarargsCollector(Object[].class);
for (List<?> l : appendResults) {
switch (l.size()) {
case 1: actual += x; continue;
}
actual += l;
}
}
// test case of an single name which is overloaded: Fooable.foo(...)
{
countTest();
if (verbosity > 3)
if (verbosity > 3)
if (verbosity > 4)
}
}
// test processing of thrown exceptions:
new InternalError("ok"),
new Throwable("fail"),
new Exception("fail"),
new MyCheckedException()
}) {
try {
countTest();
assertTrue(false);
if (verbosity > 3) {
}
if (ex instanceof RuntimeException ||
} else if (ex instanceof MyCheckedException) {
} else {
}
}
}
}
// Test error checking on bad interfaces:
String.class,
CharSequence.class,
PrivateRunnable.class,
Example.class }) {
try {
countTest(false);
} catch (IllegalArgumentException ex) {
// Object: java.lang.IllegalArgumentException:
// not a public interface: java.lang.Object
// String: java.lang.IllegalArgumentException:
// not a public interface: java.lang.String
// CharSequence: java.lang.IllegalArgumentException:
// not a single-method interface: java.lang.CharSequence
// Serializable: java.lang.IllegalArgumentException:
// not a single-method interface: java.io.Serializable
// PrivateRunnable: java.lang.IllegalArgumentException:
// not a public interface: test.java.lang.invoke.MethodHandlesTest$PrivateRunnable
// Example: java.lang.IllegalArgumentException:
// not a public interface: test.java.lang.invoke.MethodHandlesTest$Example
}
}
// Test error checking on interfaces with the wrong method type:
Fooable.class /*arity 1 & 2*/ }) {
try {
countTest(false);
} catch (WrongMethodTypeException ex) {
// Runnable: java.lang.invoke.WrongMethodTypeException:
// cannot convert MethodHandle(Object)Object[] to ()void
// Fooable: java.lang.invoke.WrongMethodTypeException:
// cannot convert MethodHandle(Object)Object[] to (Object,String)Object
}
}
}
@Test
if (CAN_SKIP_WORKING) return;
startTest("testRunnableProxy");
MethodHandle run = lookup.findStatic(lookup.lookupClass(), "runForRunnable", MethodType.methodType(void.class));
assertCalled("runForRunnable");
}
//7058630: JSR 292 method handle proxy violates contract for Object methods
r.run();
Object o = r;
r = null;
boolean eq = (o == o);
}
}
// Local abbreviated copy of sun.invoke.util.ValueConversions
// This guy tests access from outside the same package member, but inside
// the package itself.
class ValueConversions {
for (;;) {
try {
} catch (ReflectiveOperationException ex) {
// break from loop!
}
}
}
/** Return a method handle that takes the indicated number of Object
* arguments and returns an Object array of them, as if for varargs.
*/
}
MethodType vaType = MethodType.methodType(arrayType, Collections.<Class<?>>nCopies(nargs, elemType));
}
if (!elemType.isPrimitive())
for (int i = 0; i < a.length; i++)
return b;
}
static {
try {
throw err;
}
}
for (;;) {
try {
} catch (ReflectiveOperationException ex) {
// break from loop!
}
}
}
static {
try {
AS_LIST = IMPL_LOOKUP.findStatic(Arrays.class, "asList", MethodType.methodType(List.class, Object[].class));
}
/** Return a method handle that takes the indicated number of Object
* arguments and returns List.
*/
}
}
// This guy tests access from outside the same package member, but inside
// the package itself.
class PackageSibling {
return MethodHandles.lookup();
}
}