meth: {collect,spread,fold}Arguments working; better test output
authorjrose
Wed Jun 10 04:17:20 2009 -0700 (5 months ago)
changeset 16bff20cf185b1
parent 15800a2c2ff01d
child 174a545756cc3d
meth: {collect,spread,fold}Arguments working; better test output
netbeans/meth/test/jdk/java/dyn/MethodHandlesTest.java
--- a/netbeans/meth/test/jdk/java/dyn/MethodHandlesTest.java Mon Jun 08 23:03:59 2009 -0700
+++ b/netbeans/meth/test/jdk/java/dyn/MethodHandlesTest.java Wed Jun 10 04:17:20 2009 -0700
@@ -53,17 +53,26 @@ public class MethodHandlesTest {
@Test
public void testFirst() {
// left blank for debugging
+ testCollectArguments(Object.class, 0, 2);
}
// current failures
@Test @Ignore("failure in call to makeRawRetypeOnly in ToGeneric")
public void testFail_1() {
- testSpreadArguments(int.class, 6);
+ testSpreadArguments(int.class, 0, 6);
}
@Test @Ignore("failure in JVM when expanding the stack")
public void testFail_2() {
// if CONV_OP_IMPLEMENTED_MASK includes OP_SPREAD_ARGS, this crashes:
- testSpreadArguments(Object.class, 2);
+ testSpreadArguments(Object.class, 0, 2);
+ }
+ @Test @Ignore("IllArgEx failure in call to ToGeneric.make")
+ public void testFail_3() {
+ testSpreadArguments(int.class, 1, 2);
+ }
+ @Test @Ignore("IllArgEx failure in call to ToGeneric.make")
+ public void testFail_4() {
+ testCollectArguments(int.class, 1, 2);
}
public MethodHandlesTest() {
@@ -189,6 +198,19 @@ public class MethodHandlesTest {
return x.getClass().getSimpleName();
}
+ static MethodHandle changeArgTypes(MethodHandle target, Class<?> argType) {
+ return changeArgTypes(target, 0, 999, argType);
+ }
+ static MethodHandle changeArgTypes(MethodHandle target,
+ int beg, int end, Class<?> argType) {
+ MethodType targetType = target.type();
+ end = Math.min(end, targetType.parameterCount());
+ ArrayList<Class<?>> argTypes = new ArrayList<Class<?>>(targetType.parameterList());
+ Collections.fill(argTypes.subList(beg, end), argType);
+ MethodType ttype2 = MethodType.make(targetType.returnType(), argTypes);
+ return MethodHandles.convertArguments(target, ttype2);
+ }
+
// This lookup is good for all members in and under MethodHandlesTest.
static final Lookup PRIVATE = MethodHandles.lookup();
// This lookup is good for package-private members but not private ones.
@@ -313,8 +335,9 @@ public class MethodHandlesTest {
} catch (NoAccessException ex) {
noAccess = ex;
}
-// System.out.println("findStatic "+lookup+": "+defc+"."+name+"/"+type+" => "+target
-// +(noAccess == null ? "" : " !! "+noAccess));
+ if (verbosity >= 2)
+ System.out.println("findStatic "+lookup+": "+defc+"."+name+"/"+type+" => "+target
+ +(noAccess == null ? "" : " !! "+noAccess));
if (positive && noAccess != null) throw noAccess;
assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null);
if (!positive) return; // negative test failed as expected
@@ -374,8 +397,9 @@ public class MethodHandlesTest {
} catch (NoAccessException ex) {
noAccess = ex;
}
-// System.out.println("findVirtual "+lookup+": "+defc+"."+name+"/"+type+" => "+target
-// +(noAccess == null ? "" : " !! "+noAccess));
+ if (verbosity >= 2)
+ System.out.println("findVirtual "+lookup+": "+defc+"."+name+"/"+type+" => "+target
+ +(noAccess == null ? "" : " !! "+noAccess));
if (positive && noAccess != null) throw noAccess;
assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null);
if (!positive) return; // negative test failed as expected
@@ -419,8 +443,9 @@ public class MethodHandlesTest {
} catch (NoAccessException ex) {
noAccess = ex;
}
-// System.out.println("findSpecial "+defc+"."+name+"/"+type+" => "+target
-// +(noAccess == null ? "" : " !! "+noAccess));
+ if (verbosity >= 2)
+ System.out.println("findSpecial "+defc+"."+name+"/"+type+" => "+target
+ +(noAccess == null ? "" : " !! "+noAccess));
if (positive && noAccess != null) throw noAccess;
assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null);
if (!positive) return; // negative test failed as expected
@@ -474,8 +499,9 @@ public class MethodHandlesTest {
} catch (NoAccessException ex) {
noAccess = ex;
}
-// System.out.println("bind "+receiver+"."+name+"/"+type+" => "+target
-// +(noAccess == null ? "" : " !! "+noAccess));
+ if (verbosity >= 2)
+ System.out.println("bind "+receiver+"."+name+"/"+type+" => "+target
+ +(noAccess == null ? "" : " !! "+noAccess));
if (positive && noAccess != null) throw noAccess;
assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null);
if (!positive) return; // negative test failed as expected
@@ -536,8 +562,9 @@ public class MethodHandlesTest {
} catch (NoAccessException ex) {
noAccess = ex;
}
- System.out.println("unreflect "+defc+"."+name+"/"+type+" => "+target
- +(noAccess == null ? "" : " !! "+noAccess));
+ if (verbosity >= 2)
+ System.out.println("unreflect "+defc+"."+name+"/"+type+" => "+target
+ +(noAccess == null ? "" : " !! "+noAccess));
if (positive && noAccess != null) throw noAccess;
assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null);
if (!positive) return; // negative test failed as expected
@@ -682,8 +709,9 @@ public class MethodHandlesTest {
} catch (RuntimeException ex) {
error = ex;
}
- //System.out.println("convert "+id+ " to "+newType+" => "+target
- // +(error == null ? "" : " !! "+error));
+ if (verbosity >= 2)
+ System.out.println("convert "+id+ " to "+newType+" => "+target
+ +(error == null ? "" : " !! "+error));
if (positive && error != null) throw error;
assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null);
if (!positive) return; // negative test failed as expected
@@ -704,16 +732,22 @@ public class MethodHandlesTest {
System.out.println("spreadArguments "+argType);
for (int nargs = 0; nargs < 10; nargs++) {
if (argType == int.class && nargs >= 6) continue; // FIXME Fail_1
- testSpreadArguments(argType, nargs);
+ for (int pos = 0; pos < nargs; pos++) {
+ if (argType == int.class && pos > 0) continue; // FIXME Fail_3
+ testSpreadArguments(argType, pos, nargs);
+ }
}
}
}
- public void testSpreadArguments(Class<?> argType, int nargs) {
+ public void testSpreadArguments(Class<?> argType, int pos, int nargs) {
+ countTest();
MethodHandle target = ValueConversions.varargsArray(nargs);
MethodHandle target2 = changeArgTypes(target, argType);
+ if (verbosity >= 2)
+ System.out.println("spread into "+target2+" ["+pos+".."+nargs+"]");
Object[] args = randomArgs(target2.type().parameterArray());
// make sure the target does what we think it does:
- if (nargs < 5) {
+ if (pos == 0 && nargs < 5) {
Object[] check = (Object[]) MethodHandles.invoke(target, args);
assertArrayEquals(args, check);
switch (nargs) {
@@ -731,29 +765,61 @@ public class MethodHandlesTest {
break;
}
}
- MethodType newType = MethodType.make(Object.class, Object[].class);
+ List<Class<?>> newParams = new ArrayList<Class<?>>(target2.type().parameterList());
+ { // modify newParams in place
+ List<Class<?>> spreadParams = newParams.subList(pos, nargs);
+ spreadParams.clear(); spreadParams.add(Object[].class);
+ }
+ MethodType newType = MethodType.make(Object.class, newParams);
MethodHandle result = MethodHandles.spreadArguments(target2, newType);
- Object[] returnValue = (Object[]) result.invoke(args);
+ Object[] returnValue;
+ if (pos == 0) {
+ returnValue = (Object[]) result.invoke(args);
+ } else {
+ Object[] args1 = Arrays.copyOfRange(args, 0, pos+1);
+ args1[pos] = Arrays.copyOfRange(args, pos, args.length);
+ returnValue = (Object[]) MethodHandles.invoke(result, args1);
+ }
assertArrayEquals(args, returnValue);
}
- static MethodHandle changeArgTypes(MethodHandle target, Class<?> argType) {
- ArrayList<Class<?>> argTypes = new ArrayList<Class<?>>();
- for (int j = 0; j < target.type().parameterCount(); j++)
- argTypes.add(argType);
- MethodType ttype2 = MethodType.make(target.type().returnType(), argTypes);
- return MethodHandles.convertArguments(target, ttype2);
- }
-
- @Test @Ignore("unimplemented")
+ @Test
public void testCollectArguments() {
+ if (CAN_SKIP_WORKING) return;
startTest("collectArguments");
- MethodHandle target = null;
- MethodType newType = null;
- MethodHandle expResult = null;
+ for (Class<?> argType : new Class[]{Object.class, Integer.class, int.class}) {
+ if (verbosity >= 2)
+ System.out.println("collectArguments "+argType);
+ for (int nargs = 0; nargs < 10; nargs++) {
+ for (int pos = 0; pos < nargs; pos++) {
+ if (argType == int.class) continue; // FIXME Fail_4
+ testCollectArguments(argType, pos, nargs);
+ }
+ }
+ }
+ }
+ public void testCollectArguments(Class<?> argType, int pos, int nargs) {
+ countTest();
+ // fake up a MH with the same type as the desired adapter:
+ MethodHandle fake = ValueConversions.varargsArray(nargs);
+ fake = changeArgTypes(fake, argType);
+ MethodType newType = fake.type();
+ Object[] args = randomArgs(newType.parameterArray());
+ // here is what should happen:
+ Object[] collectedArgs = Arrays.copyOfRange(args, 0, pos+1);
+ collectedArgs[pos] = Arrays.copyOfRange(args, pos, args.length);
+ // here is the MH which will witness the collected argument tail:
+ MethodHandle target = ValueConversions.varargsArray(pos+1);
+ target = changeArgTypes(target, 0, pos, argType);
+ target = changeArgTypes(target, pos, pos+1, Object[].class);
+ if (verbosity >= 2)
+ System.out.println("collect from "+Arrays.asList(args)+" ["+pos+".."+nargs+"]");
MethodHandle result = MethodHandles.collectArguments(target, newType);
- assertEquals(expResult, result);
- fail("The test case is a prototype.");
+ Object[] returnValue = (Object[]) MethodHandles.invoke(result, args);
+// assertTrue(returnValue.length == pos+1 && returnValue[pos] instanceof Object[]);
+// returnValue[pos] = Arrays.asList((Object[]) returnValue[pos]);
+// collectedArgs[pos] = Arrays.asList((Object[]) collectedArgs[pos]);
+ assertArrayEquals(collectedArgs, returnValue);
}
@Test
@@ -770,6 +836,7 @@ public class MethodHandlesTest {
}
void testInsertArguments(int nargs, int pos, int ins) {
+ countTest();
MethodHandle target = ValueConversions.varargsArray(nargs + ins);
Object[] args = randomArgs(target.type().parameterArray());
List<Object> resList = Arrays.asList(args);
@@ -777,22 +844,24 @@ public class MethodHandlesTest {
List<Object> argsToInsert = argsToPass.subList(pos, pos + ins);
MethodHandle target2 = MethodHandles.insertArguments(target, pos,
(Object[]) argsToInsert.toArray());
- //System.out.println("insert: "+argsToInsert+" into "+target2);
+ if (verbosity >= 2)
+ System.out.println("insert: "+argsToInsert+" into "+target2);
argsToInsert.clear(); // remove from argsToInsert
Object res2 = MethodHandles.invoke(target2, argsToPass.toArray());
Object res2List = Arrays.asList((Object[])res2);
- //System.out.println("result: "+res2List);
+ if (verbosity >= 2)
+ System.out.println("result: "+res2List);
//if (!resList.equals(res2List))
// System.out.println("*** fail at n/p/i = "+nargs+"/"+pos+"/"+ins+": "+resList+" => "+res2List);
assertEquals(resList, res2List);
}
- @Test @Ignore("in progress")
+ @Test
public void testFoldArguments() {
- //if (CAN_SKIP_WORKING) return;
+ if (CAN_SKIP_WORKING) return;
startTest("foldArguments");
for (int nargs = 0; nargs <= 4; nargs++) {
- for (int fold = 0; fold <= 4; fold++) {
+ for (int fold = 0; fold <= nargs; fold++) {
for (int pos = 0; pos <= nargs; pos++) {
testFoldArguments(nargs, pos, fold);
}
@@ -802,19 +871,23 @@ public class MethodHandlesTest {
void testFoldArguments(int nargs, int pos, int fold) {
if (pos != 0) return; // can fold only at pos=0 for now
+ countTest();
MethodHandle target = ValueConversions.varargsList(1 + nargs);
MethodHandle combine = ValueConversions.varargsList(fold);
- List<Object> argsToPass = Arrays.asList(randomArgs(fold + nargs, Object.class));
- System.out.println("fold "+target+" with "+combine);
- MethodHandle target2 = MethodHandles.foldArguments(target, combine, fold);
+ List<Object> argsToPass = Arrays.asList(randomArgs(nargs, Object.class));
+ if (verbosity >= 2)
+ System.out.println("fold "+target+" with "+combine);
+ MethodHandle target2 = MethodHandles.foldArguments(target, combine);
// Simulate expected effect of combiner on arglist:
List<Object> expected = new ArrayList<Object>(argsToPass);
List<Object> argsToFold = expected.subList(pos, pos + fold);
- System.out.println("fold: "+argsToFold+" into "+target2);
+ if (verbosity >= 2)
+ System.out.println("fold: "+argsToFold+" into "+target2);
Object foldedArgs = MethodHandles.invoke(combine, argsToFold.toArray());
- argsToFold.clear(); argsToFold.add(foldedArgs);
+ argsToFold.add(0, foldedArgs);
Object result = MethodHandles.invoke(target2, argsToPass.toArray());
- System.out.println("result: "+result);
+ if (verbosity >= 2)
+ System.out.println("result: "+result);
if (!expected.equals(result))
System.out.println("*** fail at n/p/f = "+nargs+"/"+pos+"/"+fold+": "+argsToPass+" => "+result);
assertEquals(expected, result);
@@ -834,6 +907,7 @@ public class MethodHandlesTest {
}
void testDropArguments(int nargs, int pos, int drop) {
+ countTest();
MethodHandle target = ValueConversions.varargsArray(nargs);
Object[] args = randomArgs(target.type().parameterArray());
MethodHandle target2 = MethodHandles.dropArguments(target, pos,
@@ -893,6 +967,7 @@ public class MethodHandlesTest {
}
}
void testGuardWithTest(int nargs, Class<?> argClass) {
+ countTest();
MethodHandle test = PRIVATE.findVirtual(Object.class, "equals", MethodType.make(boolean.class, Object.class));
MethodHandle target = PRIVATE.findStatic(MethodHandlesTest.class, "targetIfEquals", MethodType.makeGeneric(nargs));
MethodHandle fallback = PRIVATE.findStatic(MethodHandlesTest.class, "fallbackIfNotEquals", MethodType.makeGeneric(nargs));
@@ -950,6 +1025,7 @@ public class MethodHandlesTest {
}
void testCatchException(Class<?> returnType, Throwable thrown, boolean throwIt, int nargs) {
+ countTest();
Class<? extends Throwable> exType = thrown.getClass();
MethodHandle throwOrReturn
= PRIVATE.findStatic(MethodHandlesTest.class, "throwOrReturn",
@@ -984,6 +1060,7 @@ public class MethodHandlesTest {
}
void testThrowException(Class<?> returnType, Throwable thrown) {
+ countTest();
Class<? extends Throwable> exType = thrown.getClass();
MethodHandle target = MethodHandles.throwException(returnType, exType);
//System.out.println("throwing with "+target+" : "+thrown);