24 */ |
24 */ |
25 |
25 |
26 /* @test |
26 /* @test |
27 * @summary unit tests for java.dyn.MethodHandles |
27 * @summary unit tests for java.dyn.MethodHandles |
28 * @compile -XDinvokedynamic MethodHandlesTest.java |
28 * @compile -XDinvokedynamic MethodHandlesTest.java |
29 * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableInvokeDynamic jdk.java.dyn.MethodHandlesTest |
29 * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableInvokeDynamic test.java.dyn.MethodHandlesTest |
30 */ |
30 */ |
31 |
31 |
32 package jdk.java.dyn; |
32 package test.java.dyn; |
33 |
33 |
34 import java.dyn.*; |
34 import java.dyn.*; |
35 import java.dyn.MethodHandles.Lookup; |
35 import java.dyn.MethodHandles.Lookup; |
36 import java.lang.reflect.*; |
36 import java.lang.reflect.*; |
37 import java.util.*; |
37 import java.util.*; |
38 import java.util.logging.Level; |
|
39 import java.util.logging.Logger; |
|
40 import org.junit.*; |
38 import org.junit.*; |
41 import static org.junit.Assert.*; |
39 import static org.junit.Assert.*; |
|
40 import static org.junit.Assume.*; |
42 |
41 |
43 |
42 |
44 /** |
43 /** |
45 * |
44 * |
46 * @author jrose |
45 * @author jrose |
47 */ |
46 */ |
48 public class MethodHandlesTest { |
47 public class MethodHandlesTest { |
49 // How much output? |
48 // How much output? |
50 static int verbosity = 1; |
49 static int verbosity = 0; |
51 |
50 |
52 // Set this true during development if you want to fast-forward to |
51 // Set this true during development if you want to fast-forward to |
53 // a particular new, non-working test. Tests which are known to |
52 // a particular new, non-working test. Tests which are known to |
54 // work (or have recently worked) test this flag and return on true. |
53 // work (or have recently worked) test this flag and return on true. |
55 static boolean CAN_SKIP_WORKING = false; |
54 static boolean CAN_SKIP_WORKING = false; |
56 //static { CAN_SKIP_WORKING = true; } |
55 //static { CAN_SKIP_WORKING = true; } |
57 |
56 |
58 // Set true to test more calls. If false, some tests are just |
57 // Set true to test more calls. If false, some tests are just |
59 // lookups, without exercising the actual method handle. |
58 // lookups, without exercising the actual method handle. |
60 static boolean DO_MORE_CALLS = false; |
59 static boolean DO_MORE_CALLS = true; |
61 |
60 |
62 |
61 |
63 @Test |
62 @Test |
64 public void testFirst() throws Throwable { |
63 public void testFirst() throws Throwable { |
65 verbosity += 9; try { |
64 verbosity += 9; try { |
66 // left blank for debugging |
65 // left blank for debugging |
67 } finally { verbosity -= 9; } |
66 } finally { printCounts(); verbosity -= 9; } |
68 } |
67 } |
69 |
68 |
70 // current failures |
69 // current failures |
71 @Test @Ignore("failure in call to makeRawRetypeOnly in ToGeneric") |
70 @Test @Ignore("failure in call to makeRawRetypeOnly in ToGeneric") |
72 public void testFail_1() throws Throwable { |
71 public void testFail_1() throws Throwable { |
|
72 // AMH.<init>: IllegalArgumentException: bad adapter (conversion=0xfffab300): adapter pushes too many parameters |
73 testSpreadArguments(int.class, 0, 6); |
73 testSpreadArguments(int.class, 0, 6); |
74 } |
74 } |
75 @Test @Ignore("failure in JVM when expanding the stack") |
75 @Test @Ignore("failure in JVM when expanding the stack using asm stub for _adapter_spread_args") |
76 public void testFail_2() throws Throwable { |
76 public void testFail_2() throws Throwable { |
77 // if CONV_OP_IMPLEMENTED_MASK includes OP_SPREAD_ARGS, this crashes: |
77 // if CONV_OP_IMPLEMENTED_MASK includes OP_SPREAD_ARGS, this crashes: |
78 testSpreadArguments(Object.class, 0, 2); |
78 testSpreadArguments(Object.class, 0, 2); |
79 } |
79 } |
80 @Test @Ignore("IllArgEx failure in call to ToGeneric.make") |
80 @Test @Ignore("IllArgEx failure in call to ToGeneric.make") |
81 public void testFail_3() throws Throwable { |
81 public void testFail_3() throws Throwable { |
|
82 // ToGeneric.<init>: UnsupportedOperationException: NYI: primitive parameters must follow references; entryType = (int,java.lang.Object)java.lang.Object |
82 testSpreadArguments(int.class, 1, 2); |
83 testSpreadArguments(int.class, 1, 2); |
83 } |
84 } |
84 @Test @Ignore("IllArgEx failure in call to ToGeneric.make") |
85 @Test @Ignore("IllArgEx failure in call to ToGeneric.make") |
85 public void testFail_4() throws Throwable { |
86 public void testFail_4() throws Throwable { |
|
87 // ToGeneric.<init>: UnsupportedOperationException: NYI: primitive parameters must follow references; entryType = (int,java.lang.Object)java.lang.Object |
86 testCollectArguments(int.class, 1, 2); |
88 testCollectArguments(int.class, 1, 2); |
87 } |
89 } |
88 @Test @Ignore("cannot collect leading primitive types") |
90 @Test @Ignore("cannot collect leading primitive types") |
89 public void testFail_5() throws Throwable { |
91 public void testFail_5() throws Throwable { |
|
92 // ToGeneric.<init>: UnsupportedOperationException: NYI: primitive parameters must follow references; entryType = (int,java.lang.Object)java.lang.Object |
90 testInvokers(MethodType.genericMethodType(2).changeParameterType(0, int.class)); |
93 testInvokers(MethodType.genericMethodType(2).changeParameterType(0, int.class)); |
91 } |
94 } |
92 @Test @Ignore("should not insert arguments beyond MethodHandlePushLimit") |
95 @Test @Ignore("should not insert arguments beyond MethodHandlePushLimit") |
93 public void testFail_6() throws Throwable { |
96 public void testFail_6() throws Throwable { |
94 testInsertArguments(0, 0, MAX_ARG_INCREASE+1); |
97 // ValueConversions.varargsArray: UnsupportedOperationException: NYI: cannot form a varargs array of length 13 |
|
98 testInsertArguments(0, 0, MAX_ARG_INCREASE+10); |
95 } |
99 } |
96 static final int MAX_ARG_INCREASE = 3; |
100 static final int MAX_ARG_INCREASE = 3; |
97 |
101 |
98 public MethodHandlesTest() { |
102 public MethodHandlesTest() { |
|
103 } |
|
104 |
|
105 @Before |
|
106 public void checkImplementedPlatform() { |
|
107 boolean platformOK = false; |
|
108 Properties properties = System.getProperties(); |
|
109 String vers = properties.getProperty("java.vm.version"); |
|
110 String name = properties.getProperty("java.vm.name"); |
|
111 String arch = properties.getProperty("os.arch"); |
|
112 if ((arch.equals("i386") || arch.equals("amd64") || |
|
113 arch.equals("sparc") || arch.equals("sparcv9")) && |
|
114 (name.contains("Client") || name.contains("Server")) |
|
115 ) { |
|
116 platformOK = true; |
|
117 } else { |
|
118 System.err.println("Skipping tests for unsupported platform: "+Arrays.asList(vers, name, arch)); |
|
119 } |
|
120 assumeTrue(platformOK); |
99 } |
121 } |
100 |
122 |
101 String testName; |
123 String testName; |
102 int posTests, negTests; |
124 int posTests, negTests; |
103 @After |
125 @After |
104 public void printCounts() { |
126 public void printCounts() { |
105 if (verbosity >= 1 && (posTests | negTests) != 0) { |
127 if (verbosity >= 2 && (posTests | negTests) != 0) { |
106 System.out.println(); |
128 System.out.println(); |
107 if (posTests != 0) System.out.println("=== "+testName+": "+posTests+" positive test cases run"); |
129 if (posTests != 0) System.out.println("=== "+testName+": "+posTests+" positive test cases run"); |
108 if (negTests != 0) System.out.println("=== "+testName+": "+negTests+" negative test cases run"); |
130 if (negTests != 0) System.out.println("=== "+testName+": "+negTests+" negative test cases run"); |
|
131 posTests = negTests = 0; |
109 } |
132 } |
110 } |
133 } |
111 void countTest(boolean positive) { |
134 void countTest(boolean positive) { |
112 if (positive) ++posTests; |
135 if (positive) ++posTests; |
113 else ++negTests; |
136 else ++negTests; |
114 } |
137 } |
115 void countTest() { countTest(true); } |
138 void countTest() { countTest(true); } |
116 void startTest(String name) { |
139 void startTest(String name) { |
117 if (testName != null) printCounts(); |
140 if (testName != null) printCounts(); |
118 if (verbosity >= 0) |
141 if (verbosity >= 1) |
119 System.out.println(name); |
142 System.out.println(name); |
120 posTests = negTests = 0; |
143 posTests = negTests = 0; |
121 testName = name; |
144 testName = name; |
122 } |
145 } |
123 |
146 |
124 @BeforeClass |
147 @BeforeClass |
125 public static void setUpClass() throws Exception { |
148 public static void setUpClass() throws Exception { |
126 calledLog.clear(); |
149 calledLog.clear(); |
127 calledLog.add(null); |
150 calledLog.add(null); |
128 nextArg = 1000000; |
151 nextArgVal = INITIAL_ARG_VAL; |
129 } |
152 } |
130 |
153 |
131 @AfterClass |
154 @AfterClass |
132 public static void tearDownClass() throws Exception { |
155 public static void tearDownClass() throws Exception { |
133 } |
156 } |
186 if (dst == boolean.class || dst == boolean.class) |
208 if (dst == boolean.class || dst == boolean.class) |
187 return ((value % 29) & 1) == 0; |
209 return ((value % 29) & 1) == 0; |
188 return null; |
210 return null; |
189 } |
211 } |
190 |
212 |
191 static int nextArg; |
213 static final int ONE_MILLION = (1000*1000), // first int value |
|
214 TEN_BILLION = (10*1000*1000*1000), // scale factor to reach upper 32 bits |
|
215 INITIAL_ARG_VAL = ONE_MILLION << 1; // <<1 makes space for sign bit; |
|
216 static long nextArgVal; |
|
217 static long nextArg(boolean moreBits) { |
|
218 long val = nextArgVal++; |
|
219 long sign = -(val & 1); // alternate signs |
|
220 val >>= 1; |
|
221 if (moreBits) |
|
222 // Guarantee some bits in the high word. |
|
223 // In any case keep the decimal representation simple-looking, |
|
224 // with lots of zeroes, so as not to make the printed decimal |
|
225 // strings unnecessarily noisy. |
|
226 val += (val % ONE_MILLION) * TEN_BILLION; |
|
227 return val ^ sign; |
|
228 } |
|
229 static int nextArg() { |
|
230 // Produce a 32-bit result something like ONE_MILLION+(smallint). |
|
231 // Example: 1_000_042. |
|
232 return (int) nextArg(false); |
|
233 } |
|
234 static long nextArg(Class<?> kind) { |
|
235 if (kind == long.class || kind == Long.class || |
|
236 kind == double.class || kind == Double.class) |
|
237 // produce a 64-bit result something like |
|
238 // ((TEN_BILLION+1) * (ONE_MILLION+(smallint))) |
|
239 // Example: 10_000_420_001_000_042. |
|
240 return nextArg(true); |
|
241 return (long) nextArg(); |
|
242 } |
|
243 |
192 static Object randomArg(Class<?> param) { |
244 static Object randomArg(Class<?> param) { |
193 Object wrap = castToWrapperOrNull(nextArg, param); |
245 Object wrap = castToWrapperOrNull(nextArg(param), param); |
194 if (wrap != null) { |
246 if (wrap != null) { |
195 nextArg++; |
|
196 return wrap; |
247 return wrap; |
197 } |
248 } |
198 // import sun.dyn.util.Wrapper; |
249 // import sun.dyn.util.Wrapper; |
199 // Wrapper wrap = Wrapper.forBasicType(dst); |
250 // Wrapper wrap = Wrapper.forBasicType(dst); |
200 // if (wrap == Wrapper.OBJECT && Wrapper.isWrapperType(dst)) |
251 // if (wrap == Wrapper.OBJECT && Wrapper.isWrapperType(dst)) |
201 // wrap = Wrapper.forWrapperType(dst); |
252 // wrap = Wrapper.forWrapperType(dst); |
202 // if (wrap != Wrapper.OBJECT) |
253 // if (wrap != Wrapper.OBJECT) |
203 // return wrap.wrap(nextArg++); |
254 // return wrap.wrap(nextArg++); |
204 if (param.isInterface() || param.isAssignableFrom(String.class)) |
255 if (param.isInterface() || param.isAssignableFrom(String.class)) |
205 return "#"+(nextArg++); |
256 return "#"+nextArg(); |
206 else |
257 else |
207 try { |
258 try { |
208 return param.newInstance(); |
259 return param.newInstance(); |
209 } catch (InstantiationException ex) { |
260 } catch (InstantiationException ex) { |
210 } catch (IllegalAccessException ex) { |
261 } catch (IllegalAccessException ex) { |
299 public static Object s3(long x) { return called("s3", x); } |
350 public static Object s3(long x) { return called("s3", x); } |
300 public static Object s4(int x, int y) { return called("s4", x, y); } |
351 public static Object s4(int x, int y) { return called("s4", x, y); } |
301 public static Object s5(long x, int y) { return called("s5", x, y); } |
352 public static Object s5(long x, int y) { return called("s5", x, y); } |
302 public static Object s6(int x, long y) { return called("s6", x, y); } |
353 public static Object s6(int x, long y) { return called("s6", x, y); } |
303 public static Object s7(float x, double y) { return called("s7", x, y); } |
354 public static Object s7(float x, double y) { return called("s7", x, y); } |
304 } |
355 |
|
356 static final Lookup EXAMPLE = MethodHandles.lookup(); // for testing findSpecial |
|
357 } |
|
358 static final Lookup EXAMPLE = Example.EXAMPLE; |
305 public static class PubExample extends Example { |
359 public static class PubExample extends Example { |
|
360 public PubExample() { super("PubExample#"+nextArg()); } |
306 } |
361 } |
307 static class SubExample extends Example { |
362 static class SubExample extends Example { |
308 @Override public void v0() { called("Sub/v0", this); } |
363 @Override public void v0() { called("Sub/v0", this); } |
309 @Override void pkg_v0() { called("Sub/pkg_v0", this); } |
364 @Override void pkg_v0() { called("Sub/pkg_v0", this); } |
310 private SubExample(int x) { called("<init>", this, x); } |
365 private SubExample(int x) { called("<init>", this, x); } |
311 public SubExample() { super("SubExample#"+(nextArg++)); } |
366 public SubExample() { super("SubExample#"+nextArg()); } |
312 } |
367 } |
313 public static interface IntExample { |
368 public static interface IntExample { |
314 public void v0(); |
369 public void v0(); |
315 static class Impl implements IntExample { |
370 static class Impl implements IntExample { |
316 public void v0() { called("Int/v0", this); } |
371 public void v0() { called("Int/v0", this); } |
317 final String name; |
372 final String name; |
318 public Impl() { name = "Example#"+(nextArg++); } |
373 public Impl() { name = "Impl#"+nextArg(); } |
|
374 @Override public String toString() { return name; } |
319 } |
375 } |
320 } |
376 } |
321 |
377 |
322 static final Object[][][] ACCESS_CASES = { |
378 static final Object[][][] ACCESS_CASES = { |
323 { { false, PUBLIC }, { false, PACKAGE }, { false, PRIVATE } }, |
379 { { false, PUBLIC }, { false, PACKAGE }, { false, PRIVATE }, { false, EXAMPLE } }, //[0]: all false |
324 { { false, PUBLIC }, { false, PACKAGE }, { true, PRIVATE } }, |
380 { { false, PUBLIC }, { false, PACKAGE }, { true, PRIVATE }, { true, EXAMPLE } }, //[1]: only PRIVATE |
325 { { false, PUBLIC }, { true, PACKAGE }, { true, PRIVATE } }, |
381 { { false, PUBLIC }, { true, PACKAGE }, { true, PRIVATE }, { true, EXAMPLE } }, //[2]: PUBLIC false |
326 { { true, PUBLIC }, { true, PACKAGE }, { true, PRIVATE } }, |
382 { { true, PUBLIC }, { true, PACKAGE }, { true, PRIVATE }, { true, EXAMPLE } }, //[3]: all true |
327 }; |
383 }; |
328 |
384 |
329 static Object[][] accessCases(Class<?> defc, String name) { |
385 static Object[][] accessCases(Class<?> defc, String name, boolean isSpecial) { |
330 if (name.contains("pri_")) { |
386 Object[][] cases; |
331 return ACCESS_CASES[1]; // PRIVATE only |
387 if (name.contains("pri_") || isSpecial) { |
332 } else if (name.contains("pkg_")) { |
388 cases = ACCESS_CASES[1]; // PRIVATE only |
333 return ACCESS_CASES[2]; // not PUBLIC |
389 } else if (name.contains("pkg_") || !Modifier.isPublic(defc.getModifiers())) { |
|
390 cases = ACCESS_CASES[2]; // not PUBLIC |
334 } else { |
391 } else { |
335 assertTrue(name.indexOf('_') < 0); |
392 assertTrue(name.indexOf('_') < 0); |
336 boolean pubc = Modifier.isPublic(defc.getModifiers()); |
393 boolean pubc = Modifier.isPublic(defc.getModifiers()); |
337 if (pubc) |
394 if (pubc) |
338 return ACCESS_CASES[3]; // all access levels |
395 cases = ACCESS_CASES[3]; // all access levels |
339 return ACCESS_CASES[2]; // PACKAGE but not PUBLIC |
396 else |
340 } |
397 cases = ACCESS_CASES[2]; // PACKAGE but not PUBLIC |
|
398 } |
|
399 if (defc != Example.class && cases[cases.length-1][1] == EXAMPLE) |
|
400 cases = Arrays.copyOfRange(cases, 0, cases.length-1); |
|
401 return cases; |
|
402 } |
|
403 static Object[][] accessCases(Class<?> defc, String name) { |
|
404 return accessCases(defc, name, false); |
341 } |
405 } |
342 |
406 |
343 @Test |
407 @Test |
344 public void testFindStatic() throws Throwable { |
408 public void testFindStatic() throws Throwable { |
345 if (CAN_SKIP_WORKING) return; |
409 if (CAN_SKIP_WORKING) return; |
434 String methodName = name.substring(1 + name.indexOf('/')); // foo/bar => foo |
500 String methodName = name.substring(1 + name.indexOf('/')); // foo/bar => foo |
435 MethodType type = MethodType.methodType(ret, params); |
501 MethodType type = MethodType.methodType(ret, params); |
436 MethodHandle target = null; |
502 MethodHandle target = null; |
437 RuntimeException noAccess = null; |
503 RuntimeException noAccess = null; |
438 try { |
504 try { |
|
505 if (verbosity >= 4) System.out.println("lookup via "+lookup+" of "+defc+" "+name+type); |
439 target = lookup.findVirtual(defc, methodName, type); |
506 target = lookup.findVirtual(defc, methodName, type); |
440 } catch (NoAccessException ex) { |
507 } catch (NoAccessException ex) { |
441 noAccess = ex; |
508 noAccess = ex; |
442 } |
509 } |
443 if (verbosity >= 2) |
510 if (verbosity >= 3) |
444 System.out.println("findVirtual "+lookup+": "+defc+"."+name+"/"+type+" => "+target |
511 System.out.println("findVirtual "+lookup+": "+defc.getName()+"."+name+"/"+type+" => "+target |
445 +(noAccess == null ? "" : " !! "+noAccess)); |
512 +(noAccess == null ? "" : " !! "+noAccess)); |
446 if (positive && noAccess != null) throw noAccess; |
513 if (positive && noAccess != null) throw noAccess; |
447 assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null); |
514 assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null); |
448 if (!positive) return; // negative test failed as expected |
515 if (!positive) return; // negative test failed as expected |
449 Class<?>[] paramsWithSelf = cat(array(Class[].class, (Class)defc), params); |
516 Class<?>[] paramsWithSelf = cat(array(Class[].class, (Class)defc), params); |
450 MethodType typeWithSelf = MethodType.methodType(ret, paramsWithSelf); |
517 MethodType typeWithSelf = MethodType.methodType(ret, paramsWithSelf); |
451 MethodType ttype = target.type(); |
518 assertEquals(typeWithSelf, target.type()); |
452 ttype = ttype.changeParameterType(0, defc); // FIXME: test this |
|
453 assertEquals(typeWithSelf, ttype); |
|
454 assertTrue(target.toString().contains(methodName)); // rough check |
519 assertTrue(target.toString().contains(methodName)); // rough check |
455 if (!DO_MORE_CALLS && lookup != PRIVATE) return; |
520 if (!DO_MORE_CALLS && lookup != PRIVATE) return; |
456 Object[] argsWithSelf = randomArgs(paramsWithSelf); |
521 Object[] argsWithSelf = randomArgs(paramsWithSelf); |
457 if (rcvc != defc) argsWithSelf[0] = randomArg(rcvc); |
522 if (rcvc != defc) argsWithSelf[0] = randomArg(rcvc); |
458 printCalled(target, name, argsWithSelf); |
523 printCalled(target, name, argsWithSelf); |
459 target.invokeVarargs(argsWithSelf); |
524 target.invokeVarargs(argsWithSelf); |
460 assertCalled(name, argsWithSelf); |
525 assertCalled(name, argsWithSelf); |
461 System.out.print(':'); |
526 if (verbosity >= 1) |
|
527 System.out.print(':'); |
462 } |
528 } |
463 |
529 |
464 @Test |
530 @Test |
465 public void testFindSpecial() throws Throwable { |
531 public void testFindSpecial() throws Throwable { |
466 if (CAN_SKIP_WORKING) return; |
532 if (CAN_SKIP_WORKING) return; |
467 startTest("findSpecial"); |
533 startTest("findSpecial"); |
468 testFindSpecial(Example.class, void.class, "v0"); |
534 testFindSpecial(SubExample.class, Example.class, void.class, "v0"); |
469 testFindSpecial(Example.class, void.class, "pkg_v0"); |
535 testFindSpecial(SubExample.class, Example.class, void.class, "pkg_v0"); |
470 testFindSpecial(false, PRIVATE, Example.class, void.class, "<init>", int.class); |
536 // Do some negative testing: |
471 testFindSpecial(false, PRIVATE, Example.class, void.class, "bogus"); |
537 for (Lookup lookup : new Lookup[]{ PRIVATE, EXAMPLE, PACKAGE, PUBLIC }) { |
472 } |
538 testFindSpecial(false, lookup, Object.class, Example.class, void.class, "v0"); |
473 |
539 testFindSpecial(false, lookup, SubExample.class, Example.class, void.class, "<init>", int.class); |
474 void testFindSpecial(Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable { |
540 testFindSpecial(false, lookup, SubExample.class, Example.class, void.class, "s0"); |
475 testFindSpecial(true, PRIVATE, defc, ret, name, params); |
541 testFindSpecial(false, lookup, SubExample.class, Example.class, void.class, "bogus"); |
476 testFindSpecial(false, PACKAGE, defc, ret, name, params); |
542 } |
477 testFindSpecial(false, PUBLIC, defc, ret, name, params); |
543 } |
478 } |
544 |
479 void testFindSpecial(boolean positive, Lookup lookup, Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable { |
545 void testFindSpecial(Class<?> specialCaller, |
|
546 Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable { |
|
547 testFindSpecial(true, EXAMPLE, specialCaller, defc, ret, name, params); |
|
548 testFindSpecial(true, PRIVATE, specialCaller, defc, ret, name, params); |
|
549 testFindSpecial(false, PACKAGE, specialCaller, defc, ret, name, params); |
|
550 testFindSpecial(false, PUBLIC, specialCaller, defc, ret, name, params); |
|
551 } |
|
552 void testFindSpecial(boolean positive, Lookup lookup, Class<?> specialCaller, |
|
553 Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable { |
480 countTest(positive); |
554 countTest(positive); |
481 MethodType type = MethodType.methodType(ret, params); |
555 MethodType type = MethodType.methodType(ret, params); |
482 MethodHandle target = null; |
556 MethodHandle target = null; |
483 RuntimeException noAccess = null; |
557 RuntimeException noAccess = null; |
484 try { |
558 try { |
485 target = lookup.findSpecial(defc, name, type, defc); |
559 if (verbosity >= 4) System.out.println("lookup via "+lookup+" of "+defc+" "+name+type); |
|
560 target = lookup.findSpecial(defc, name, type, specialCaller); |
486 } catch (NoAccessException ex) { |
561 } catch (NoAccessException ex) { |
487 noAccess = ex; |
562 noAccess = ex; |
488 } |
563 } |
489 if (verbosity >= 2) |
564 if (verbosity >= 3) |
490 System.out.println("findSpecial "+defc+"."+name+"/"+type+" => "+target |
565 System.out.println("findSpecial from "+specialCaller.getName()+" to "+defc.getName()+"."+name+"/"+type+" => "+target |
491 +(noAccess == null ? "" : " !! "+noAccess)); |
566 +(target == null ? "" : target.type()) |
|
567 +(noAccess == null ? "" : " !! "+noAccess)); |
492 if (positive && noAccess != null) throw noAccess; |
568 if (positive && noAccess != null) throw noAccess; |
493 assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null); |
569 assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null); |
494 if (!positive) return; // negative test failed as expected |
570 if (!positive) return; // negative test failed as expected |
495 Class<?>[] paramsWithSelf = cat(array(Class[].class, (Class)defc), params); |
571 assertEquals(specialCaller, target.type().parameterType(0)); |
|
572 assertEquals(type, target.type().dropParameterTypes(0,1)); |
|
573 Class<?>[] paramsWithSelf = cat(array(Class[].class, (Class)specialCaller), params); |
496 MethodType typeWithSelf = MethodType.methodType(ret, paramsWithSelf); |
574 MethodType typeWithSelf = MethodType.methodType(ret, paramsWithSelf); |
497 MethodType ttype = target.type(); |
|
498 ttype = ttype.changeParameterType(0, defc); // FIXME: test this |
|
499 assertEquals(typeWithSelf, ttype); |
|
500 assertTrue(target.toString().contains(name)); // rough check |
575 assertTrue(target.toString().contains(name)); // rough check |
501 if (!DO_MORE_CALLS && lookup != PRIVATE) return; |
576 if (!DO_MORE_CALLS && lookup != PRIVATE && lookup != EXAMPLE) return; |
502 Object[] args = randomArgs(paramsWithSelf); |
577 Object[] args = randomArgs(paramsWithSelf); |
503 printCalled(target, name, args); |
578 printCalled(target, name, args); |
504 target.invokeVarargs(args); |
579 target.invokeVarargs(args); |
505 assertCalled(name, args); |
580 assertCalled(name, args); |
506 System.out.print(':'); |
|
507 } |
581 } |
508 |
582 |
509 @Test |
583 @Test |
510 public void testBind() throws Throwable { |
584 public void testBind() throws Throwable { |
511 if (CAN_SKIP_WORKING) return; |
585 if (CAN_SKIP_WORKING) return; |
565 testUnreflect(Example.class, true, void.class, "pkg_s0"); |
641 testUnreflect(Example.class, true, void.class, "pkg_s0"); |
566 testUnreflect(Example.class, true, void.class, "pri_s0"); |
642 testUnreflect(Example.class, true, void.class, "pri_s0"); |
567 |
643 |
568 testUnreflect(Example.class, true, Object.class, "s1", Object.class); |
644 testUnreflect(Example.class, true, Object.class, "s1", Object.class); |
569 testUnreflect(Example.class, true, Object.class, "s2", int.class); |
645 testUnreflect(Example.class, true, Object.class, "s2", int.class); |
570 //testUnreflect(Example.class, true, Object.class, "s3", long.class); |
646 testUnreflect(Example.class, true, Object.class, "s3", long.class); |
571 //testUnreflect(Example.class, true, Object.class, "s4", int.class, int.class); |
647 testUnreflect(Example.class, true, Object.class, "s4", int.class, int.class); |
572 //testUnreflect(Example.class, true, Object.class, "s5", long.class, int.class); |
648 testUnreflect(Example.class, true, Object.class, "s5", long.class, int.class); |
573 //testUnreflect(Example.class, true, Object.class, "s6", int.class, long.class); |
649 testUnreflect(Example.class, true, Object.class, "s6", int.class, long.class); |
574 |
650 |
575 testUnreflect(Example.class, false, void.class, "v0"); |
651 testUnreflect(Example.class, false, void.class, "v0"); |
576 testUnreflect(Example.class, false, void.class, "pkg_v0"); |
652 testUnreflect(Example.class, false, void.class, "pkg_v0"); |
577 testUnreflect(Example.class, false, void.class, "pri_v0"); |
653 testUnreflect(Example.class, false, void.class, "pri_v0"); |
578 testUnreflect(Example.class, false, Object.class, "v1", Object.class); |
654 testUnreflect(Example.class, false, Object.class, "v1", Object.class); |
582 testUnreflect(Example.class, false, Object.class, "v2", int.class, int.class); |
658 testUnreflect(Example.class, false, Object.class, "v2", int.class, int.class); |
583 } |
659 } |
584 |
660 |
585 void testUnreflect(Class<?> defc, boolean isStatic, Class<?> ret, String name, Class<?>... params) throws Throwable { |
661 void testUnreflect(Class<?> defc, boolean isStatic, Class<?> ret, String name, Class<?>... params) throws Throwable { |
586 for (Object[] ac : accessCases(defc, name)) { |
662 for (Object[] ac : accessCases(defc, name)) { |
587 testUnreflect((Boolean)ac[0], (Lookup)ac[1], defc, isStatic, ret, name, params); |
663 testUnreflectMaybeSpecial(null, (Boolean)ac[0], (Lookup)ac[1], defc, (isStatic ? null : defc), ret, name, params); |
588 } |
664 } |
589 } |
665 } |
590 void testUnreflect(boolean positive, Lookup lookup, Class<?> defc, boolean isStatic, Class<?> ret, String name, Class<?>... params) throws Throwable { |
666 void testUnreflect(Class<?> defc, Class<?> rcvc, Class<?> ret, String name, Class<?>... params) throws Throwable { |
|
667 for (Object[] ac : accessCases(defc, name)) { |
|
668 testUnreflectMaybeSpecial(null, (Boolean)ac[0], (Lookup)ac[1], defc, rcvc, ret, name, params); |
|
669 } |
|
670 } |
|
671 void testUnreflectMaybeSpecial(Class<?> specialCaller, |
|
672 boolean positive, Lookup lookup, |
|
673 Class<?> defc, Class<?> rcvc, Class<?> ret, String name, Class<?>... params) throws Throwable { |
591 countTest(positive); |
674 countTest(positive); |
592 MethodType type = MethodType.methodType(ret, params); |
675 MethodType type = MethodType.methodType(ret, params); |
593 Method rmethod = null; |
676 Method rmethod = null; |
594 MethodHandle target = null; |
677 MethodHandle target = null; |
595 RuntimeException noAccess = null; |
678 RuntimeException noAccess = null; |
596 try { |
679 try { |
597 rmethod = defc.getDeclaredMethod(name, params); |
680 rmethod = defc.getDeclaredMethod(name, params); |
598 } catch (NoSuchMethodException ex) { |
681 } catch (NoSuchMethodException ex) { |
599 throw new NoAccessException(ex); |
682 throw new NoAccessException(ex); |
600 } |
683 } |
601 assertEquals(isStatic, Modifier.isStatic(rmethod.getModifiers())); |
684 boolean isStatic = (rcvc == null); |
|
685 boolean isSpecial = (specialCaller != null); |
602 try { |
686 try { |
603 target = lookup.unreflect(rmethod); |
687 if (verbosity >= 4) System.out.println("lookup via "+lookup+" of "+defc+" "+name+type); |
|
688 if (isSpecial) |
|
689 target = lookup.unreflectSpecial(rmethod, specialCaller); |
|
690 else |
|
691 target = lookup.unreflect(rmethod); |
604 } catch (NoAccessException ex) { |
692 } catch (NoAccessException ex) { |
605 noAccess = ex; |
693 noAccess = ex; |
606 } |
694 } |
607 if (verbosity >= 2) |
695 if (verbosity >= 3) |
608 System.out.println("unreflect "+defc+"."+name+"/"+type+" => "+target |
696 System.out.println("unreflect"+(isSpecial?"Special":"")+" "+defc.getName()+"."+name+"/"+type |
609 +(noAccess == null ? "" : " !! "+noAccess)); |
697 +(!isSpecial ? "" : " specialCaller="+specialCaller) |
|
698 +( isStatic ? "" : " receiver="+rcvc) |
|
699 +" => "+target |
|
700 +(noAccess == null ? "" : " !! "+noAccess)); |
610 if (positive && noAccess != null) throw noAccess; |
701 if (positive && noAccess != null) throw noAccess; |
611 assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null); |
702 assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null); |
612 if (!positive) return; // negative test failed as expected |
703 if (!positive) return; // negative test failed as expected |
|
704 assertEquals(isStatic, Modifier.isStatic(rmethod.getModifiers())); |
613 Class<?>[] paramsMaybeWithSelf = params; |
705 Class<?>[] paramsMaybeWithSelf = params; |
614 if (!isStatic) { |
706 if (!isStatic) { |
615 paramsMaybeWithSelf = cat(array(Class[].class, (Class)defc), params); |
707 paramsMaybeWithSelf = cat(array(Class[].class, (Class)rcvc), params); |
616 } |
708 } |
617 MethodType typeMaybeWithSelf = MethodType.methodType(ret, paramsMaybeWithSelf); |
709 MethodType typeMaybeWithSelf = MethodType.methodType(ret, paramsMaybeWithSelf); |
618 MethodType ttype = target.type(); |
710 if (isStatic) { |
619 if (!isStatic) |
711 assertEquals(typeMaybeWithSelf, target.type()); |
620 ttype = ttype.changeParameterType(0, defc); // FIXME: test this |
712 } else { |
621 assertEquals(typeMaybeWithSelf, ttype); |
713 if (isSpecial) |
|
714 assertEquals(specialCaller, target.type().parameterType(0)); |
|
715 else |
|
716 assertEquals(defc, target.type().parameterType(0)); |
|
717 assertEquals(typeMaybeWithSelf, target.type().changeParameterType(0, rcvc)); |
|
718 } |
622 Object[] argsMaybeWithSelf = randomArgs(paramsMaybeWithSelf); |
719 Object[] argsMaybeWithSelf = randomArgs(paramsMaybeWithSelf); |
623 printCalled(target, name, argsMaybeWithSelf); |
720 printCalled(target, name, argsMaybeWithSelf); |
624 target.invokeVarargs(argsMaybeWithSelf); |
721 target.invokeVarargs(argsMaybeWithSelf); |
625 assertCalled(name, argsMaybeWithSelf); |
722 assertCalled(name, argsMaybeWithSelf); |
626 System.out.print(':'); |
723 if (verbosity >= 1) |
627 } |
724 System.out.print(':'); |
628 |
725 } |
629 @Test @Ignore("unimplemented") |
726 |
|
727 void testUnreflectSpecial(Class<?> defc, Class<?> rcvc, Class<?> ret, String name, Class<?>... params) throws Throwable { |
|
728 for (Object[] ac : accessCases(defc, name, true)) { |
|
729 Class<?> specialCaller = rcvc; |
|
730 testUnreflectMaybeSpecial(specialCaller, (Boolean)ac[0], (Lookup)ac[1], defc, rcvc, ret, name, params); |
|
731 } |
|
732 } |
|
733 |
|
734 @Test |
630 public void testUnreflectSpecial() throws Throwable { |
735 public void testUnreflectSpecial() throws Throwable { |
631 Lookup lookup = PRIVATE; // FIXME: test more lookups than this one |
736 if (CAN_SKIP_WORKING) return; |
632 startTest("unreflectSpecial"); |
737 startTest("unreflectSpecial"); |
633 Method m = null; |
738 testUnreflectSpecial(Example.class, Example.class, void.class, "v0"); |
634 MethodHandle expResult = null; |
739 testUnreflectSpecial(Example.class, SubExample.class, void.class, "v0"); |
635 MethodHandle result = lookup.unreflectSpecial(m, Example.class); |
740 testUnreflectSpecial(Example.class, Example.class, void.class, "pkg_v0"); |
636 assertEquals(expResult, result); |
741 testUnreflectSpecial(Example.class, SubExample.class, void.class, "pkg_v0"); |
637 fail("The test case is a prototype."); |
742 testUnreflectSpecial(Example.class, Example.class, Object.class, "v2", int.class, int.class); |
|
743 testUnreflectSpecial(Example.class, SubExample.class, Object.class, "v2", int.class, int.class); |
|
744 testUnreflectMaybeSpecial(Example.class, false, PRIVATE, Example.class, Example.class, void.class, "s0"); |
638 } |
745 } |
639 |
746 |
640 public static class HasFields { |
747 public static class HasFields { |
641 boolean fZ = false; |
748 boolean fZ = false; |
642 byte fB = (byte)'B'; |
749 byte fB = (byte)'B'; |
784 assertEquals(f.get(fields), value); // clean to start with |
891 assertEquals(f.get(fields), value); // clean to start with |
785 for (int i = 0; i <= 1; i++) { |
892 for (int i = 0; i <= 1; i++) { |
786 Object putValue = randomArg(type); |
893 Object putValue = randomArg(type); |
787 if (isStatic) { |
894 if (isStatic) { |
788 if (type == int.class) |
895 if (type == int.class) |
789 mh.<void>invoke((int)(Integer)putValue); // do these exactly |
896 mh.<void>invokeExact((int)(Integer)putValue); // do these exactly |
790 else |
897 else |
791 mh.<void>invoke(putValue); |
898 mh.<void>invokeExact(putValue); |
792 } else { |
899 } else { |
793 if (type == int.class) |
900 if (type == int.class) |
794 mh.<void>invoke((Object) fields, (int)(Integer)putValue); |
901 mh.<void>invokeExact((Object) fields, (int)(Integer)putValue); |
795 else |
902 else |
796 mh.<void>invoke((Object) fields, putValue); |
903 mh.<void>invokeExact((Object) fields, putValue); |
797 } |
904 } |
798 assertEquals(f.get(fields), putValue); |
905 assertEquals(f.get(fields), putValue); |
799 } |
906 } |
800 f.set(fields, value); // put it back |
907 f.set(fields, value); // put it back |
801 } |
908 } |
802 |
909 |
803 @Test |
910 @Test |
804 public void testArrayElementGetter() throws Throwable { |
911 public void testArrayElementGetter() throws Throwable { |
805 startTest("arrayElementGetter"); |
912 startTest("arrayElementGetter"); |
806 testArrayElementGetterSetter(new Object[10], false); |
913 testArrayElementGetterSetter(false); |
807 testArrayElementGetterSetter(new String[10], false); |
|
808 testArrayElementGetterSetter(new int[10], false); |
|
809 // FIXME: Do the other primitive types. |
|
810 //testArrayElementGetterSetter(new float[10], false); |
|
811 } |
914 } |
812 |
915 |
813 @Test |
916 @Test |
814 public void testArrayElementSetter() throws Throwable { |
917 public void testArrayElementSetter() throws Throwable { |
815 startTest("arrayElementSetter"); |
918 startTest("arrayElementSetter"); |
816 testArrayElementGetterSetter(new Object[10], true); |
919 testArrayElementGetterSetter(true); |
817 testArrayElementGetterSetter(new String[10], true); |
920 } |
818 testArrayElementGetterSetter(new int[10], true); |
921 |
819 // FIXME: Do the other primitive types. |
922 public void testArrayElementGetterSetter(boolean testSetter) throws Throwable { |
820 //testArrayElementGetterSetter(new float[10], true); |
923 testArrayElementGetterSetter(new Object[10], testSetter); |
|
924 testArrayElementGetterSetter(new String[10], testSetter); |
|
925 testArrayElementGetterSetter(new boolean[10], testSetter); |
|
926 testArrayElementGetterSetter(new byte[10], testSetter); |
|
927 testArrayElementGetterSetter(new char[10], testSetter); |
|
928 testArrayElementGetterSetter(new short[10], testSetter); |
|
929 testArrayElementGetterSetter(new int[10], testSetter); |
|
930 testArrayElementGetterSetter(new float[10], testSetter); |
|
931 testArrayElementGetterSetter(new long[10], testSetter); |
|
932 testArrayElementGetterSetter(new double[10], testSetter); |
821 } |
933 } |
822 |
934 |
823 public void testArrayElementGetterSetter(Object array, boolean testSetter) throws Throwable { |
935 public void testArrayElementGetterSetter(Object array, boolean testSetter) throws Throwable { |
824 countTest(true); |
936 countTest(true); |
|
937 if (verbosity >= 2) System.out.println("array type = "+array.getClass().getComponentType().getName()+"["+Array.getLength(array)+"]"); |
825 Class<?> arrayType = array.getClass(); |
938 Class<?> arrayType = array.getClass(); |
826 Class<?> elemType = arrayType.getComponentType(); |
939 Class<?> elemType = arrayType.getComponentType(); |
827 MethodType expType = !testSetter |
940 MethodType expType = !testSetter |
828 ? MethodType.methodType(elemType, arrayType, int.class) |
941 ? MethodType.methodType(elemType, arrayType, int.class) |
829 : MethodType.methodType(void.class, arrayType, int.class, elemType); |
942 : MethodType.methodType(void.class, arrayType, int.class, elemType); |
830 MethodHandle mh = !testSetter |
943 MethodHandle mh = !testSetter |
831 ? MethodHandles.arrayElementGetter(arrayType) |
944 ? MethodHandles.arrayElementGetter(arrayType) |
832 : MethodHandles.arrayElementSetter(arrayType); |
945 : MethodHandles.arrayElementSetter(arrayType); |
833 assertSame(mh.type(), expType); |
946 assertSame(mh.type(), expType); |
834 //assertEquals(mh.toString(), f.getName()); |
947 if (elemType != int.class && elemType != boolean.class) { |
|
948 MethodType gtype; |
|
949 if (true) { // FIXME: remove this path (and remove <void> below in the mh.invokes) |
|
950 gtype = mh.type().changeParameterType(0, Object.class); |
|
951 if (testSetter) |
|
952 gtype = gtype.changeParameterType(2, Object.class); |
|
953 else |
|
954 gtype = gtype.changeReturnType(Object.class); |
|
955 } else |
|
956 // FIXME: This simpler path hits a bug in convertArguments => ToGeneric |
|
957 gtype = mh.type().generic().changeParameterType(1, int.class); |
|
958 mh = MethodHandles.convertArguments(mh, gtype); |
|
959 } |
835 Object sawValue, expValue; |
960 Object sawValue, expValue; |
836 List<Object> model = array2list(array); |
961 List<Object> model = array2list(array); |
837 int length = Array.getLength(array); |
962 int length = Array.getLength(array); |
838 for (int i = 0; i < length; i++) { |
963 for (int i = 0; i < length; i++) { |
839 // update array element |
964 // update array element |
840 Object random = randomArg(elemType); |
965 Object random = randomArg(elemType); |
841 model.set(i, random); |
966 model.set(i, random); |
842 if (testSetter) { |
967 if (testSetter) { |
843 if (elemType == int.class) |
968 if (elemType == int.class) |
844 mh.<void>invoke((int[]) array, i, (int)(Integer)random); |
969 mh.<void>invokeExact((int[]) array, i, (int)(Integer)random); |
|
970 else if (elemType == boolean.class) |
|
971 mh.<void>invokeExact((boolean[]) array, i, (boolean)(Boolean)random); |
845 else |
972 else |
846 mh.invokeGeneric(array, i, random); |
973 mh.<void>invokeExact(array, i, random); |
847 assertEquals(model, array2list(array)); |
974 assertEquals(model, array2list(array)); |
848 } else { |
975 } else { |
849 Array.set(array, i, random); |
976 Array.set(array, i, random); |
850 |
977 } |
|
978 if (verbosity >= 5) { |
|
979 List<Object> array2list = array2list(array); |
|
980 System.out.println("a["+i+"]="+random+" => "+array2list); |
|
981 if (!array2list.equals(model)) |
|
982 System.out.println("*** != "+model); |
851 } |
983 } |
852 // observe array element |
984 // observe array element |
853 sawValue = Array.get(array, i); |
985 sawValue = Array.get(array, i); |
854 if (!testSetter) { |
986 if (!testSetter) { |
855 expValue = sawValue; |
987 expValue = sawValue; |
856 if (elemType == int.class) |
988 if (elemType == int.class) |
857 sawValue = mh.<int>invoke((int[]) array, i); |
989 sawValue = mh.<int>invokeExact((int[]) array, i); |
|
990 else if (elemType == boolean.class) |
|
991 sawValue = mh.<boolean>invokeExact((boolean[]) array, i); |
858 else |
992 else |
859 sawValue = mh.invokeGeneric(array, i); |
993 sawValue = mh.invokeExact(array, i); |
860 assertEquals(sawValue, expValue); |
994 assertEquals(sawValue, expValue); |
861 assertEquals(model, array2list(array)); |
995 assertEquals(model, array2list(array)); |
862 } |
996 } |
863 } |
997 } |
864 } |
998 } |
1081 @Test |
1218 @Test |
1082 public void testSpreadArguments() throws Throwable { |
1219 public void testSpreadArguments() throws Throwable { |
1083 if (CAN_SKIP_WORKING) return; |
1220 if (CAN_SKIP_WORKING) return; |
1084 startTest("spreadArguments"); |
1221 startTest("spreadArguments"); |
1085 for (Class<?> argType : new Class[]{Object.class, Integer.class, int.class}) { |
1222 for (Class<?> argType : new Class[]{Object.class, Integer.class, int.class}) { |
1086 if (verbosity >= 2) |
1223 if (verbosity >= 3) |
1087 System.out.println("spreadArguments "+argType); |
1224 System.out.println("spreadArguments "+argType); |
|
1225 // FIXME: enable _adapter_spread_args and fix Fail_2 |
1088 for (int nargs = 0; nargs < 10; nargs++) { |
1226 for (int nargs = 0; nargs < 10; nargs++) { |
1089 if (argType == int.class && nargs >= 6) continue; // FIXME Fail_1 |
1227 if (argType == int.class && nargs >= 6) continue; // FIXME Fail_1 |
1090 for (int pos = 0; pos < nargs; pos++) { |
1228 for (int pos = 0; pos < nargs; pos++) { |
1091 if (argType == int.class && pos > 0) continue; // FIXME Fail_3 |
1229 if (argType == int.class && pos > 0) continue; // FIXME Fail_3 |
1092 testSpreadArguments(argType, pos, nargs); |
1230 testSpreadArguments(argType, pos, nargs); |
1093 } |
1231 } |
1094 } |
1232 } |
1095 } |
1233 } |
1096 } |
1234 } |
1097 public void testSpreadArguments(Class<?> argType, int pos, int nargs) throws Throwable { |
1235 public void testSpreadArguments(Class<?> argType, int pos, int nargs) throws Throwable { |
1098 countTest(); |
1236 countTest(); |
1099 MethodHandle target = ValueConversions.varargsArray(nargs); |
1237 MethodHandle target = ValueConversions.varargsArray(nargs); |
1100 MethodHandle target2 = changeArgTypes(target, argType); |
1238 MethodHandle target2 = changeArgTypes(target, argType); |
1101 if (verbosity >= 2) |
1239 if (verbosity >= 3) |
1102 System.out.println("spread into "+target2+" ["+pos+".."+nargs+"]"); |
1240 System.out.println("spread into "+target2+" ["+pos+".."+nargs+"]"); |
1103 Object[] args = randomArgs(target2.type().parameterArray()); |
1241 Object[] args = randomArgs(target2.type().parameterArray()); |
1104 // make sure the target does what we think it does: |
1242 // make sure the target does what we think it does: |
1105 if (pos == 0 && nargs < 5) { |
1243 if (pos == 0 && nargs < 5) { |
1106 Object[] check = (Object[]) target.invokeVarargs(args); |
1244 Object[] check = (Object[]) target.invokeVarargs(args); |
1107 assertArrayEquals(args, check); |
1245 assertArrayEquals(args, check); |
1108 switch (nargs) { |
1246 switch (nargs) { |
1109 case 0: |
1247 case 0: |
1110 check = target.<Object[]>invoke(); |
1248 check = target.<Object[]>invokeExact(); |
1111 assertArrayEquals(args, check); |
1249 assertArrayEquals(args, check); |
1112 break; |
1250 break; |
1113 case 1: |
1251 case 1: |
1114 check = target.<Object[]>invoke(args[0]); |
1252 check = target.<Object[]>invokeExact(args[0]); |
1115 assertArrayEquals(args, check); |
1253 assertArrayEquals(args, check); |
1116 break; |
1254 break; |
1117 case 2: |
1255 case 2: |
1118 check = target.<Object[]>invoke(args[0], args[1]); |
1256 check = target.<Object[]>invokeExact(args[0], args[1]); |
1119 assertArrayEquals(args, check); |
1257 assertArrayEquals(args, check); |
1120 break; |
1258 break; |
1121 } |
1259 } |
1122 } |
1260 } |
1123 List<Class<?>> newParams = new ArrayList<Class<?>>(target2.type().parameterList()); |
1261 List<Class<?>> newParams = new ArrayList<Class<?>>(target2.type().parameterList()); |
1263 if (pos != 0) return; // can fold only at pos=0 for now |
1401 if (pos != 0) return; // can fold only at pos=0 for now |
1264 countTest(); |
1402 countTest(); |
1265 MethodHandle target = ValueConversions.varargsList(1 + nargs); |
1403 MethodHandle target = ValueConversions.varargsList(1 + nargs); |
1266 MethodHandle combine = ValueConversions.varargsList(fold); |
1404 MethodHandle combine = ValueConversions.varargsList(fold); |
1267 List<Object> argsToPass = Arrays.asList(randomArgs(nargs, Object.class)); |
1405 List<Object> argsToPass = Arrays.asList(randomArgs(nargs, Object.class)); |
1268 if (verbosity >= 2) |
1406 if (verbosity >= 3) |
1269 System.out.println("fold "+target+" with "+combine); |
1407 System.out.println("fold "+target+" with "+combine); |
1270 MethodHandle target2 = MethodHandles.foldArguments(target, combine); |
1408 MethodHandle target2 = MethodHandles.foldArguments(target, combine); |
1271 // Simulate expected effect of combiner on arglist: |
1409 // Simulate expected effect of combiner on arglist: |
1272 List<Object> expected = new ArrayList<Object>(argsToPass); |
1410 List<Object> expected = new ArrayList<Object>(argsToPass); |
1273 List<Object> argsToFold = expected.subList(pos, pos + fold); |
1411 List<Object> argsToFold = expected.subList(pos, pos + fold); |
1274 if (verbosity >= 2) |
1412 if (verbosity >= 3) |
1275 System.out.println("fold: "+argsToFold+" into "+target2); |
1413 System.out.println("fold: "+argsToFold+" into "+target2); |
1276 Object foldedArgs = combine.invokeVarargs(argsToFold); |
1414 Object foldedArgs = combine.invokeVarargs(argsToFold); |
1277 argsToFold.add(0, foldedArgs); |
1415 argsToFold.add(0, foldedArgs); |
1278 Object result = target2.invokeVarargs(argsToPass); |
1416 Object result = target2.invokeVarargs(argsToPass); |
1279 if (verbosity >= 2) |
1417 if (verbosity >= 3) |
1280 System.out.println("result: "+result); |
1418 System.out.println("result: "+result); |
1281 if (!expected.equals(result)) |
1419 if (!expected.equals(result)) |
1282 System.out.println("*** fail at n/p/f = "+nargs+"/"+pos+"/"+fold+": "+argsToPass+" => "+result); |
1420 System.out.println("*** fail at n/p/f = "+nargs+"/"+pos+"/"+fold+": "+argsToPass+" => "+result); |
1283 assertEquals(expected, result); |
1421 assertEquals(expected, result); |
1284 } |
1422 } |
1393 if (testRetCode) assertEquals(code, result); |
1531 if (testRetCode) assertEquals(code, result); |
1394 assertCalled("invokee", args); |
1532 assertCalled("invokee", args); |
1395 // varargs invoker #0 |
1533 // varargs invoker #0 |
1396 calledLog.clear(); |
1534 calledLog.clear(); |
1397 inv = MethodHandles.varargsInvoker(type, 0); |
1535 inv = MethodHandles.varargsInvoker(type, 0); |
1398 result = inv.invoke(target, args); |
1536 result = inv.invokeExact(target, args); |
1399 if (testRetCode) assertEquals(code, result); |
1537 if (testRetCode) assertEquals(code, result); |
1400 assertCalled("invokee", args); |
1538 assertCalled("invokee", args); |
1401 if (nargs >= 1) { |
1539 if (nargs >= 1) { |
1402 // varargs invoker #1 |
1540 // varargs invoker #1 |
1403 calledLog.clear(); |
1541 calledLog.clear(); |
1404 inv = MethodHandles.varargsInvoker(type, 1); |
1542 inv = MethodHandles.varargsInvoker(type, 1); |
1405 result = inv.invoke(target, args[0], Arrays.copyOfRange(args, 1, nargs)); |
1543 result = inv.invokeExact(target, args[0], Arrays.copyOfRange(args, 1, nargs)); |
1406 if (testRetCode) assertEquals(code, result); |
1544 if (testRetCode) assertEquals(code, result); |
1407 assertCalled("invokee", args); |
1545 assertCalled("invokee", args); |
1408 } |
1546 } |
1409 if (nargs >= 2) { |
1547 if (nargs >= 2) { |
1410 // varargs invoker #2 |
1548 // varargs invoker #2 |
1411 calledLog.clear(); |
1549 calledLog.clear(); |
1412 inv = MethodHandles.varargsInvoker(type, 2); |
1550 inv = MethodHandles.varargsInvoker(type, 2); |
1413 result = inv.invoke(target, args[0], args[1], Arrays.copyOfRange(args, 2, nargs)); |
1551 result = inv.invokeExact(target, args[0], args[1], Arrays.copyOfRange(args, 2, nargs)); |
1414 if (testRetCode) assertEquals(code, result); |
1552 if (testRetCode) assertEquals(code, result); |
1415 assertCalled("invokee", args); |
1553 assertCalled("invokee", args); |
1416 } |
1554 } |
1417 if (nargs >= 3) { |
1555 if (nargs >= 3) { |
1418 // varargs invoker #3 |
1556 // varargs invoker #3 |
1419 calledLog.clear(); |
1557 calledLog.clear(); |
1420 inv = MethodHandles.varargsInvoker(type, 3); |
1558 inv = MethodHandles.varargsInvoker(type, 3); |
1421 result = inv.invoke(target, args[0], args[1], args[2], Arrays.copyOfRange(args, 3, nargs)); |
1559 result = inv.invokeExact(target, args[0], args[1], args[2], Arrays.copyOfRange(args, 3, nargs)); |
1422 if (testRetCode) assertEquals(code, result); |
1560 if (testRetCode) assertEquals(code, result); |
1423 assertCalled("invokee", args); |
1561 assertCalled("invokee", args); |
1424 } |
1562 } |
1425 for (int k = 0; k <= nargs; k++) { |
1563 for (int k = 0; k <= nargs; k++) { |
1426 // varargs invoker #0..N |
1564 // varargs invoker #0..N |
1678 assertNotSame(mode, surprise, boo); |
1817 assertNotSame(mode, surprise, boo); |
1679 identity = MethodHandles.convertArguments(identity, MethodType.genericMethodType(1)); |
1818 identity = MethodHandles.convertArguments(identity, MethodType.genericMethodType(1)); |
1680 surprise = MethodHandles.convertArguments(surprise, MethodType.genericMethodType(1)); |
1819 surprise = MethodHandles.convertArguments(surprise, MethodType.genericMethodType(1)); |
1681 Object x = 42; |
1820 Object x = 42; |
1682 for (int i = 0; i < okCount; i++) { |
1821 for (int i = 0; i < okCount; i++) { |
1683 Object y = identity.invoke(x); |
1822 Object y = identity.invokeExact(x); |
1684 assertEquals(x, y); |
1823 assertEquals(x, y); |
1685 Object z = surprise.invoke(x); |
1824 Object z = surprise.invokeExact(x); |
1686 assertEquals(x, z); |
1825 assertEquals(x, z); |
1687 } |
1826 } |
1688 boo.boo("Boo!"); |
1827 boo.boo("Boo!"); |
1689 Object y = identity.invoke(x); |
1828 Object y = identity.invokeExact(x); |
1690 assertEquals(x, y); |
1829 assertEquals(x, y); |
1691 try { |
1830 try { |
1692 Object z = surprise.invoke(x); |
1831 Object z = surprise.invokeExact(x); |
1693 System.out.println("Failed to throw; got z="+z); |
1832 System.out.println("Failed to throw; got z="+z); |
1694 assertTrue(false); |
1833 assertTrue(false); |
1695 } catch (Exception ex) { |
1834 } catch (Exception ex) { |
1696 if (verbosity > 1) |
1835 if (verbosity > 2) |
1697 System.out.println("caught "+ex); |
1836 System.out.println("caught "+ex); |
1698 if (verbosity > 2) |
1837 if (verbosity > 3) |
1699 ex.printStackTrace(); |
1838 ex.printStackTrace(); |
1700 assertTrue(ex instanceof ClassCastException |
1839 assertTrue(ex instanceof ClassCastException |
1701 // FIXME: accept only one of the two for any given unit test |
1840 // FIXME: accept only one of the two for any given unit test |
1702 || ex instanceof WrongMethodTypeException |
1841 || ex instanceof WrongMethodTypeException |
1703 ); |
1842 ); |
1704 } |
1843 } |
1705 } |
1844 } |
1706 |
1845 |
|
1846 static Example userMethod(Object o, String s, int i) { |
|
1847 called("userMethod", o, s, i); |
|
1848 return null; |
|
1849 } |
|
1850 |
|
1851 @Test |
|
1852 public void testUserClassInSignature() throws Throwable { |
|
1853 if (CAN_SKIP_WORKING) return; |
|
1854 startTest("testUserClassInSignature"); |
|
1855 Lookup lookup = MethodHandles.lookup(); |
|
1856 String name; MethodType mt; MethodHandle mh; |
|
1857 Object[] args; |
|
1858 |
|
1859 // Try a static method. |
|
1860 name = "userMethod"; |
|
1861 mt = MethodType.methodType(Example.class, Object.class, String.class, int.class); |
|
1862 mh = lookup.findStatic(lookup.lookupClass(), name, mt); |
|
1863 assertEquals(mt, mh.type()); |
|
1864 assertEquals(Example.class, mh.type().returnType()); |
|
1865 args = randomArgs(mh.type().parameterArray()); |
|
1866 mh.invokeVarargs(args); |
|
1867 assertCalled(name, args); |
|
1868 |
|
1869 // Try a virtual method. |
|
1870 name = "v2"; |
|
1871 mt = MethodType.methodType(Object.class, Object.class, int.class); |
|
1872 mh = lookup.findVirtual(Example.class, name, mt); |
|
1873 assertEquals(mt, mh.type().dropParameterTypes(0,1)); |
|
1874 assertTrue(mh.type().parameterList().contains(Example.class)); |
|
1875 args = randomArgs(mh.type().parameterArray()); |
|
1876 mh.invokeVarargs(args); |
|
1877 assertCalled(name, args); |
|
1878 } |
1707 } |
1879 } |
1708 // Local abbreviated copy of sun.dyn.util.ValueConversions |
1880 // Local abbreviated copy of sun.dyn.util.ValueConversions |
1709 class ValueConversions { |
1881 class ValueConversions { |
1710 private static final Lookup IMPL_LOOKUP = MethodHandles.lookup(); |
1882 private static final Lookup IMPL_LOOKUP = MethodHandles.lookup(); |
1711 private static final Object[] NO_ARGS_ARRAY = {}; |
1883 private static final Object[] NO_ARGS_ARRAY = {}; |