meth: tests for {permute,filter}Arguments, {exact,generic,varargs,dynamic}invoker
authorjrose
Fri Jun 19 03:02:04 2009 -0700 (5 months ago)
changeset 19afa2631a7ed5
parent 18ebfb233ce72a
child 20fa6241266623
meth: tests for {permute,filter}Arguments, {exact,generic,varargs,dynamic}invoker
netbeans/meth/test/jdk/java/dyn/MethodHandlesTest.java
--- a/netbeans/meth/test/jdk/java/dyn/MethodHandlesTest.java Sat Jun 13 00:06:45 2009 -0700
+++ b/netbeans/meth/test/jdk/java/dyn/MethodHandlesTest.java Fri Jun 19 03:02:04 2009 -0700
@@ -29,18 +29,9 @@ import sun.dyn.util.Wrapper;
import sun.dyn.util.Wrapper;
import java.dyn.*;
import java.dyn.MethodHandles.Lookup;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import org.junit.After;
-import org.junit.AfterClass;
-import org.junit.BeforeClass;
-import org.junit.Ignore;
-import org.junit.Test;
+import java.lang.reflect.*;
+import java.util.*;
+import org.junit.*;
import sun.dyn.util.ValueConversions;
import static org.junit.Assert.*;
@@ -52,8 +43,9 @@ public class MethodHandlesTest {
@Test
public void testFirst() throws Throwable {
- // left blank for debugging
- testCollectArguments(Object.class, 0, 2);
+ verbosity += 9; try {
+ // left blank for debugging
+ } finally { verbosity -= 9; }
}
// current failures
@@ -73,6 +65,10 @@ public class MethodHandlesTest {
@Test @Ignore("IllArgEx failure in call to ToGeneric.make")
public void testFail_4() throws Throwable {
testCollectArguments(int.class, 1, 2);
+ }
+ @Test @Ignore("cannot collect leading primitive types")
+ public void testFail_5() throws Throwable {
+ testInvokers(MethodType.makeGeneric(2).changeParameterType(0, int.class));
}
public MethodHandlesTest() {
@@ -665,9 +661,9 @@ public class MethodHandlesTest {
}
@Test
- public void testConvertArguments_pairwise() throws Throwable {
- if (CAN_SKIP_WORKING) return;
- startTest("convertArguments/pairwise");
+ public void testConvertArguments() throws Throwable {
+ if (CAN_SKIP_WORKING) return;
+ startTest("convertArguments");
testConvert(Callee.ofType(1), null, "id", int.class);
testConvert(Callee.ofType(1), null, "id", String.class);
testConvert(Callee.ofType(1), null, "id", Integer.class);
@@ -722,6 +718,47 @@ public class MethodHandlesTest {
assertEquals(convResult, result);
System.out.print(':');
}
+
+ @Test
+ public void testPermuteArguments() throws Throwable {
+ if (CAN_SKIP_WORKING) return;
+ startTest("permuteArguments");
+ for (int inargs = 1; inargs <= 4; inargs++) {
+ Object[] args = randomArgs(inargs, Integer.class);
+ int numcases = 1;
+ for (int outargs = 0; outargs <= 4; outargs++) {
+ int[] reorder = new int[outargs];
+ for (int cas = 0; cas < numcases; cas++) {
+ for (int i = 0, c = cas; i < outargs; i++) {
+ reorder[i] = c % inargs;
+ c /= inargs;
+ }
+ testPermuteArguments(args, reorder);
+ }
+ numcases *= inargs;
+ }
+ }
+ }
+
+ void testPermuteArguments(Object[] args, int[] reorder) throws Throwable {
+ countTest();
+ int inargs = args.length, outargs = reorder.length;
+ if (verbosity >= 2)
+ System.out.println("permuteArguments "+Arrays.toString(reorder));
+ Object[] permArgs = new Object[outargs];
+ for (int i = 0; i < outargs; i++)
+ permArgs[i] = args[reorder[i]];
+ if (verbosity >= 3) {
+ System.out.println("in args: "+Arrays.asList(args));
+ System.out.println("out args: "+Arrays.asList(permArgs));
+ }
+ MethodHandle target = ValueConversions.varargsList(outargs);
+ target = MethodHandles.permuteArguments(target, MethodType.makeGeneric(inargs), reorder);
+ Object result = MethodHandles.invoke(target, args);
+ Object expected = Arrays.asList(permArgs);
+ assertEquals(expected, result);
+ }
+
@Test
public void testSpreadArguments() throws Throwable {
@@ -857,6 +894,40 @@ public class MethodHandlesTest {
}
@Test
+ public void testFilterArguments() throws Throwable {
+ if (CAN_SKIP_WORKING) return;
+ startTest("filterArguments");
+ for (int nargs = 1; nargs <= 6; nargs++) {
+ for (int pos = 0; pos < nargs; pos++) {
+ testFilterArguments(nargs, pos);
+ }
+ }
+ }
+
+ void testFilterArguments(int nargs, int pos) throws Throwable {
+ countTest();
+ MethodHandle target = ValueConversions.varargsList(nargs);
+ MethodHandle filter = ValueConversions.varargsList(1);
+ filter = MethodHandles.convertArguments(filter, filter.type().generic());
+ Object[] argsToPass = randomArgs(nargs, Object.class);
+ if (verbosity >= 2)
+ System.out.println("filter "+target+" at "+pos+" with "+filter);
+ MethodHandle[] filters = new MethodHandle[pos*2+1];
+ filters[pos] = filter;
+ MethodHandle target2 = MethodHandles.filterArguments(target, filters);
+ // Simulate expected effect of filter on arglist:
+ Object[] filteredArgs = argsToPass.clone();
+ filteredArgs[pos] = filter.invoke(filteredArgs[pos]);
+ List<Object> expected = Arrays.asList(filteredArgs);
+ Object result = MethodHandles.invoke(target2, argsToPass);
+ if (verbosity >= 2)
+ System.out.println("result: "+result);
+ if (!expected.equals(result))
+ System.out.println("*** fail at n/p = "+nargs+"/"+pos+": "+argsToPass+" => "+result);
+ assertEquals(expected, result);
+ }
+
+ @Test
public void testFoldArguments() throws Throwable {
if (CAN_SKIP_WORKING) return;
startTest("foldArguments");
@@ -922,6 +993,142 @@ public class MethodHandlesTest {
//if (!resList.equals(res2List))
// System.out.println("*** fail at n/p/d = "+nargs+"/"+pos+"/"+drop+": "+argsToDrop+" => "+res2List);
assertEquals(resList, res2List);
+ }
+
+ @Test
+ public void testInvokers() throws Throwable {
+ if (CAN_SKIP_WORKING) return;
+ startTest("exactInvoker, genericInvoker, varargsInvoker, dynamicInvoker");
+ // exactInvoker, genericInvoker, varargsInvoker[0..N], dynamicInvoker
+ Set<MethodType> done = new HashSet<MethodType>();
+ for (int i = 0; i <= 6; i++) {
+ MethodType gtype = MethodType.makeGeneric(i);
+ for (Class<?> argType : new Class[]{Object.class, Integer.class, int.class}) {
+ for (int j = -1; j < i; j++) {
+ MethodType type = gtype;
+ if (j < 0)
+ type = type.changeReturnType(argType);
+ else if (argType == void.class)
+ continue;
+ else
+ type = type.changeParameterType(j, argType);
+ if (argType.isPrimitive() && j != i-1) continue; // FIXME Fail_5
+ if (done.add(type))
+ testInvokers(type);
+ MethodType vtype = type.changeReturnType(void.class);
+ if (done.add(vtype))
+ testInvokers(vtype);
+ }
+ }
+ }
+ }
+
+ public void testInvokers(MethodType type) throws Throwable {
+ if (verbosity >= 2)
+ System.out.println("test invokers for "+type);
+ int nargs = type.parameterCount();
+ boolean testRetCode = type.returnType() != void.class;
+ MethodHandle target = PRIVATE.findStatic(MethodHandlesTest.class, "invokee",
+ MethodType.makeGeneric(0, true));
+ target = MethodHandles.collectArguments(target, type);
+ Object[] args = randomArgs(type.parameterArray());
+ List<Object> targetPlusArgs = new ArrayList<Object>(Arrays.asList(args));
+ targetPlusArgs.add(0, target);
+ int code = (Integer) invokee(args);
+ Object log = logEntry("invokee", args);
+ assertEquals(log.hashCode(), code);
+ assertCalled("invokee", args);
+ MethodHandle inv;
+ Object result;
+ // exact invoker
+ countTest();
+ calledLog.clear();
+ inv = MethodHandles.exactInvoker(type);
+ result = MethodHandles.invoke(inv, targetPlusArgs.toArray());
+ if (testRetCode) assertEquals(code, result);
+ assertCalled("invokee", args);
+ // generic invoker
+ countTest();
+ inv = MethodHandles.genericInvoker(type);
+ if (nargs <= 3) {
+ calledLog.clear();
+ switch (nargs) {
+ case 0:
+ result = inv.invoke(target);
+ break;
+ case 1:
+ result = inv.invoke(target, args[0]);
+ break;
+ case 2:
+ result = inv.invoke(target, args[0], args[1]);
+ break;
+ case 3:
+ result = inv.invoke(target, args[0], args[1], args[2]);
+ break;
+ }
+ if (testRetCode) assertEquals(code, result);
+ assertCalled("invokee", args);
+ }
+ calledLog.clear();
+ result = MethodHandles.invoke(inv, targetPlusArgs.toArray());
+ if (testRetCode) assertEquals(code, result);
+ assertCalled("invokee", args);
+ // varargs invoker #0
+ calledLog.clear();
+ inv = MethodHandles.varargsInvoker(type, 0);
+ result = inv.invoke(target, args);
+ if (testRetCode) assertEquals(code, result);
+ assertCalled("invokee", args);
+ if (nargs >= 1) {
+ // varargs invoker #1
+ calledLog.clear();
+ inv = MethodHandles.varargsInvoker(type, 1);
+ result = inv.invoke(target, args[0], Arrays.copyOfRange(args, 1, nargs));
+ if (testRetCode) assertEquals(code, result);
+ assertCalled("invokee", args);
+ }
+ if (nargs >= 2) {
+ // varargs invoker #2
+ calledLog.clear();
+ inv = MethodHandles.varargsInvoker(type, 2);
+ result = inv.invoke(target, args[0], args[1], Arrays.copyOfRange(args, 2, nargs));
+ if (testRetCode) assertEquals(code, result);
+ assertCalled("invokee", args);
+ }
+ if (nargs >= 3) {
+ // varargs invoker #3
+ calledLog.clear();
+ inv = MethodHandles.varargsInvoker(type, 3);
+ result = inv.invoke(target, args[0], args[1], args[2], Arrays.copyOfRange(args, 3, nargs));
+ if (testRetCode) assertEquals(code, result);
+ assertCalled("invokee", args);
+ }
+ for (int k = 0; k <= nargs; k++) {
+ // varargs invoker #0..N
+ countTest();
+ calledLog.clear();
+ inv = MethodHandles.varargsInvoker(type, k);
+ List<Object> targetPlusVarArgs = new ArrayList<Object>(targetPlusArgs);
+ List<Object> tailList = targetPlusVarArgs.subList(1+k, 1+nargs);
+ Object[] tail = tailList.toArray();
+ tailList.clear(); tailList.add(tail);
+ result = MethodHandles.invoke(inv, targetPlusVarArgs.toArray());
+ if (testRetCode) assertEquals(code, result);
+ assertCalled("invokee", args);
+ }
+ // dynamic invoker
+ countTest();
+ CallSite site = new CallSite(MethodHandlesTest.class, "foo", type);
+ inv = MethodHandles.dynamicInvoker(site);
+ site.setTarget(target);
+ calledLog.clear();
+ result = MethodHandles.invoke(inv, args);
+ if (testRetCode) assertEquals(code, result);
+ assertCalled("invokee", args);
+ }
+
+ static Object invokee(Object... args) {
+ return called("invokee", args).hashCode();
}
private static final String MISSING_ARG = "missingArg";