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 if (defc.getClassLoader() != null) // detune due to 6939196 |
452 ttype = ttype.changeParameterType(0, defc); // FIXME: test this |
519 assertEquals(typeWithSelf.dropParameterTypes(0,1), |
453 assertEquals(typeWithSelf, ttype); |
520 target.type().dropParameterTypes(0,1)); |
|
521 else // FIXME: use only this test when 6939196 is fixed |
|
522 assertEquals(typeWithSelf, target.type()); |
454 assertTrue(target.toString().contains(methodName)); // rough check |
523 assertTrue(target.toString().contains(methodName)); // rough check |
455 if (!DO_MORE_CALLS && lookup != PRIVATE) return; |
524 if (!DO_MORE_CALLS && lookup != PRIVATE) return; |
456 Object[] argsWithSelf = randomArgs(paramsWithSelf); |
525 Object[] argsWithSelf = randomArgs(paramsWithSelf); |
457 if (rcvc != defc) argsWithSelf[0] = randomArg(rcvc); |
526 if (rcvc != defc) argsWithSelf[0] = randomArg(rcvc); |
458 printCalled(target, name, argsWithSelf); |
527 printCalled(target, name, argsWithSelf); |
459 target.invokeVarargs(argsWithSelf); |
528 target.invokeVarargs(argsWithSelf); |
460 assertCalled(name, argsWithSelf); |
529 assertCalled(name, argsWithSelf); |
461 System.out.print(':'); |
530 if (verbosity >= 1) |
|
531 System.out.print(':'); |
462 } |
532 } |
463 |
533 |
464 @Test |
534 @Test |
465 public void testFindSpecial() throws Throwable { |
535 public void testFindSpecial() throws Throwable { |
466 if (CAN_SKIP_WORKING) return; |
536 if (CAN_SKIP_WORKING) return; |
467 startTest("findSpecial"); |
537 startTest("findSpecial"); |
468 testFindSpecial(Example.class, void.class, "v0"); |
538 testFindSpecial(SubExample.class, Example.class, void.class, "v0"); |
469 testFindSpecial(Example.class, void.class, "pkg_v0"); |
539 testFindSpecial(SubExample.class, Example.class, void.class, "pkg_v0"); |
470 testFindSpecial(false, PRIVATE, Example.class, void.class, "<init>", int.class); |
540 // Do some negative testing: |
471 testFindSpecial(false, PRIVATE, Example.class, void.class, "bogus"); |
541 for (Lookup lookup : new Lookup[]{ PRIVATE, EXAMPLE, PACKAGE, PUBLIC }) { |
472 } |
542 testFindSpecial(false, lookup, Object.class, Example.class, void.class, "v0"); |
473 |
543 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 { |
544 testFindSpecial(false, lookup, SubExample.class, Example.class, void.class, "s0"); |
475 testFindSpecial(true, PRIVATE, defc, ret, name, params); |
545 testFindSpecial(false, lookup, SubExample.class, Example.class, void.class, "bogus"); |
476 testFindSpecial(false, PACKAGE, defc, ret, name, params); |
546 } |
477 testFindSpecial(false, PUBLIC, defc, ret, name, params); |
547 } |
478 } |
548 |
479 void testFindSpecial(boolean positive, Lookup lookup, Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable { |
549 void testFindSpecial(Class<?> specialCaller, |
|
550 Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable { |
|
551 testFindSpecial(true, EXAMPLE, specialCaller, defc, ret, name, params); |
|
552 testFindSpecial(true, PRIVATE, specialCaller, defc, ret, name, params); |
|
553 testFindSpecial(false, PACKAGE, specialCaller, defc, ret, name, params); |
|
554 testFindSpecial(false, PUBLIC, specialCaller, defc, ret, name, params); |
|
555 } |
|
556 void testFindSpecial(boolean positive, Lookup lookup, Class<?> specialCaller, |
|
557 Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable { |
480 countTest(positive); |
558 countTest(positive); |
481 MethodType type = MethodType.methodType(ret, params); |
559 MethodType type = MethodType.methodType(ret, params); |
482 MethodHandle target = null; |
560 MethodHandle target = null; |
483 RuntimeException noAccess = null; |
561 RuntimeException noAccess = null; |
484 try { |
562 try { |
485 target = lookup.findSpecial(defc, name, type, defc); |
563 if (verbosity >= 4) System.out.println("lookup via "+lookup+" of "+defc+" "+name+type); |
|
564 target = lookup.findSpecial(defc, name, type, specialCaller); |
486 } catch (NoAccessException ex) { |
565 } catch (NoAccessException ex) { |
487 noAccess = ex; |
566 noAccess = ex; |
488 } |
567 } |
489 if (verbosity >= 2) |
568 if (verbosity >= 3) |
490 System.out.println("findSpecial "+defc+"."+name+"/"+type+" => "+target |
569 System.out.println("findSpecial from "+specialCaller.getName()+" to "+defc.getName()+"."+name+"/"+type+" => "+target |
491 +(noAccess == null ? "" : " !! "+noAccess)); |
570 +(target == null ? "" : target.type()) |
|
571 +(noAccess == null ? "" : " !! "+noAccess)); |
492 if (positive && noAccess != null) throw noAccess; |
572 if (positive && noAccess != null) throw noAccess; |
493 assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null); |
573 assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null); |
494 if (!positive) return; // negative test failed as expected |
574 if (!positive) return; // negative test failed as expected |
495 Class<?>[] paramsWithSelf = cat(array(Class[].class, (Class)defc), params); |
575 assertEquals(specialCaller, target.type().parameterType(0)); |
|
576 assertEquals(type, target.type().dropParameterTypes(0,1)); |
|
577 Class<?>[] paramsWithSelf = cat(array(Class[].class, (Class)specialCaller), params); |
496 MethodType typeWithSelf = MethodType.methodType(ret, paramsWithSelf); |
578 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 |
579 assertTrue(target.toString().contains(name)); // rough check |
501 if (!DO_MORE_CALLS && lookup != PRIVATE) return; |
580 if (!DO_MORE_CALLS && lookup != PRIVATE && lookup != EXAMPLE) return; |
502 Object[] args = randomArgs(paramsWithSelf); |
581 Object[] args = randomArgs(paramsWithSelf); |
503 printCalled(target, name, args); |
582 printCalled(target, name, args); |
504 target.invokeVarargs(args); |
583 target.invokeVarargs(args); |
505 assertCalled(name, args); |
584 assertCalled(name, args); |
506 System.out.print(':'); |
|
507 } |
585 } |
508 |
586 |
509 @Test |
587 @Test |
510 public void testBind() throws Throwable { |
588 public void testBind() throws Throwable { |
511 if (CAN_SKIP_WORKING) return; |
589 if (CAN_SKIP_WORKING) return; |
565 testUnreflect(Example.class, true, void.class, "pkg_s0"); |
645 testUnreflect(Example.class, true, void.class, "pkg_s0"); |
566 testUnreflect(Example.class, true, void.class, "pri_s0"); |
646 testUnreflect(Example.class, true, void.class, "pri_s0"); |
567 |
647 |
568 testUnreflect(Example.class, true, Object.class, "s1", Object.class); |
648 testUnreflect(Example.class, true, Object.class, "s1", Object.class); |
569 testUnreflect(Example.class, true, Object.class, "s2", int.class); |
649 testUnreflect(Example.class, true, Object.class, "s2", int.class); |
570 //testUnreflect(Example.class, true, Object.class, "s3", long.class); |
650 testUnreflect(Example.class, true, Object.class, "s3", long.class); |
571 //testUnreflect(Example.class, true, Object.class, "s4", int.class, int.class); |
651 testUnreflect(Example.class, true, Object.class, "s4", int.class, int.class); |
572 //testUnreflect(Example.class, true, Object.class, "s5", long.class, int.class); |
652 testUnreflect(Example.class, true, Object.class, "s5", long.class, int.class); |
573 //testUnreflect(Example.class, true, Object.class, "s6", int.class, long.class); |
653 testUnreflect(Example.class, true, Object.class, "s6", int.class, long.class); |
574 |
654 |
575 testUnreflect(Example.class, false, void.class, "v0"); |
655 testUnreflect(Example.class, false, void.class, "v0"); |
576 testUnreflect(Example.class, false, void.class, "pkg_v0"); |
656 testUnreflect(Example.class, false, void.class, "pkg_v0"); |
577 testUnreflect(Example.class, false, void.class, "pri_v0"); |
657 testUnreflect(Example.class, false, void.class, "pri_v0"); |
578 testUnreflect(Example.class, false, Object.class, "v1", Object.class); |
658 testUnreflect(Example.class, false, Object.class, "v1", Object.class); |
582 testUnreflect(Example.class, false, Object.class, "v2", int.class, int.class); |
662 testUnreflect(Example.class, false, Object.class, "v2", int.class, int.class); |
583 } |
663 } |
584 |
664 |
585 void testUnreflect(Class<?> defc, boolean isStatic, Class<?> ret, String name, Class<?>... params) throws Throwable { |
665 void testUnreflect(Class<?> defc, boolean isStatic, Class<?> ret, String name, Class<?>... params) throws Throwable { |
586 for (Object[] ac : accessCases(defc, name)) { |
666 for (Object[] ac : accessCases(defc, name)) { |
587 testUnreflect((Boolean)ac[0], (Lookup)ac[1], defc, isStatic, ret, name, params); |
667 testUnreflectMaybeSpecial(null, (Boolean)ac[0], (Lookup)ac[1], defc, (isStatic ? null : defc), ret, name, params); |
588 } |
668 } |
589 } |
669 } |
590 void testUnreflect(boolean positive, Lookup lookup, Class<?> defc, boolean isStatic, Class<?> ret, String name, Class<?>... params) throws Throwable { |
670 void testUnreflect(Class<?> defc, Class<?> rcvc, Class<?> ret, String name, Class<?>... params) throws Throwable { |
|
671 for (Object[] ac : accessCases(defc, name)) { |
|
672 testUnreflectMaybeSpecial(null, (Boolean)ac[0], (Lookup)ac[1], defc, rcvc, ret, name, params); |
|
673 } |
|
674 } |
|
675 void testUnreflectMaybeSpecial(Class<?> specialCaller, |
|
676 boolean positive, Lookup lookup, |
|
677 Class<?> defc, Class<?> rcvc, Class<?> ret, String name, Class<?>... params) throws Throwable { |
591 countTest(positive); |
678 countTest(positive); |
592 MethodType type = MethodType.methodType(ret, params); |
679 MethodType type = MethodType.methodType(ret, params); |
593 Method rmethod = null; |
680 Method rmethod = null; |
594 MethodHandle target = null; |
681 MethodHandle target = null; |
595 RuntimeException noAccess = null; |
682 RuntimeException noAccess = null; |
596 try { |
683 try { |
597 rmethod = defc.getDeclaredMethod(name, params); |
684 rmethod = defc.getDeclaredMethod(name, params); |
598 } catch (NoSuchMethodException ex) { |
685 } catch (NoSuchMethodException ex) { |
599 throw new NoAccessException(ex); |
686 throw new NoAccessException(ex); |
600 } |
687 } |
601 assertEquals(isStatic, Modifier.isStatic(rmethod.getModifiers())); |
688 boolean isStatic = (rcvc == null); |
|
689 boolean isSpecial = (specialCaller != null); |
602 try { |
690 try { |
603 target = lookup.unreflect(rmethod); |
691 if (verbosity >= 4) System.out.println("lookup via "+lookup+" of "+defc+" "+name+type); |
|
692 if (isSpecial) |
|
693 target = lookup.unreflectSpecial(rmethod, specialCaller); |
|
694 else |
|
695 target = lookup.unreflect(rmethod); |
604 } catch (NoAccessException ex) { |
696 } catch (NoAccessException ex) { |
605 noAccess = ex; |
697 noAccess = ex; |
606 } |
698 } |
607 if (verbosity >= 2) |
699 if (verbosity >= 3) |
608 System.out.println("unreflect "+defc+"."+name+"/"+type+" => "+target |
700 System.out.println("unreflect"+(isSpecial?"Special":"")+" "+defc.getName()+"."+name+"/"+type |
609 +(noAccess == null ? "" : " !! "+noAccess)); |
701 +(!isSpecial ? "" : " specialCaller="+specialCaller) |
|
702 +( isStatic ? "" : " receiver="+rcvc) |
|
703 +" => "+target |
|
704 +(noAccess == null ? "" : " !! "+noAccess)); |
610 if (positive && noAccess != null) throw noAccess; |
705 if (positive && noAccess != null) throw noAccess; |
611 assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null); |
706 assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null); |
612 if (!positive) return; // negative test failed as expected |
707 if (!positive) return; // negative test failed as expected |
|
708 assertEquals(isStatic, Modifier.isStatic(rmethod.getModifiers())); |
613 Class<?>[] paramsMaybeWithSelf = params; |
709 Class<?>[] paramsMaybeWithSelf = params; |
614 if (!isStatic) { |
710 if (!isStatic) { |
615 paramsMaybeWithSelf = cat(array(Class[].class, (Class)defc), params); |
711 paramsMaybeWithSelf = cat(array(Class[].class, (Class)rcvc), params); |
616 } |
712 } |
617 MethodType typeMaybeWithSelf = MethodType.methodType(ret, paramsMaybeWithSelf); |
713 MethodType typeMaybeWithSelf = MethodType.methodType(ret, paramsMaybeWithSelf); |
618 MethodType ttype = target.type(); |
714 if (isStatic) { |
619 if (!isStatic) |
715 assertEquals(typeMaybeWithSelf, target.type()); |
620 ttype = ttype.changeParameterType(0, defc); // FIXME: test this |
716 } else { |
621 assertEquals(typeMaybeWithSelf, ttype); |
717 if (defc.getClassLoader() != null) // detune due to 6939196 |
|
718 assertEquals(typeMaybeWithSelf.dropParameterTypes(0,1), |
|
719 target.type().dropParameterTypes(0,1)); |
|
720 else // FIXME: use only this test when 6939196 is fixed |
|
721 if (isSpecial) |
|
722 assertEquals(specialCaller, target.type().parameterType(0)); |
|
723 else |
|
724 assertEquals(defc, target.type().parameterType(0)); |
|
725 assertEquals(typeMaybeWithSelf, target.type().changeParameterType(0, rcvc)); |
|
726 } |
622 Object[] argsMaybeWithSelf = randomArgs(paramsMaybeWithSelf); |
727 Object[] argsMaybeWithSelf = randomArgs(paramsMaybeWithSelf); |
623 printCalled(target, name, argsMaybeWithSelf); |
728 printCalled(target, name, argsMaybeWithSelf); |
624 target.invokeVarargs(argsMaybeWithSelf); |
729 target.invokeVarargs(argsMaybeWithSelf); |
625 assertCalled(name, argsMaybeWithSelf); |
730 assertCalled(name, argsMaybeWithSelf); |
626 System.out.print(':'); |
731 if (verbosity >= 1) |
627 } |
732 System.out.print(':'); |
628 |
733 } |
629 @Test @Ignore("unimplemented") |
734 |
|
735 void testUnreflectSpecial(Class<?> defc, Class<?> rcvc, Class<?> ret, String name, Class<?>... params) throws Throwable { |
|
736 for (Object[] ac : accessCases(defc, name, true)) { |
|
737 Class<?> specialCaller = rcvc; |
|
738 testUnreflectMaybeSpecial(specialCaller, (Boolean)ac[0], (Lookup)ac[1], defc, rcvc, ret, name, params); |
|
739 } |
|
740 } |
|
741 |
|
742 @Test |
630 public void testUnreflectSpecial() throws Throwable { |
743 public void testUnreflectSpecial() throws Throwable { |
631 Lookup lookup = PRIVATE; // FIXME: test more lookups than this one |
744 if (CAN_SKIP_WORKING) return; |
632 startTest("unreflectSpecial"); |
745 startTest("unreflectSpecial"); |
633 Method m = null; |
746 testUnreflectSpecial(Example.class, Example.class, void.class, "v0"); |
634 MethodHandle expResult = null; |
747 testUnreflectSpecial(Example.class, SubExample.class, void.class, "v0"); |
635 MethodHandle result = lookup.unreflectSpecial(m, Example.class); |
748 testUnreflectSpecial(Example.class, Example.class, void.class, "pkg_v0"); |
636 assertEquals(expResult, result); |
749 testUnreflectSpecial(Example.class, SubExample.class, void.class, "pkg_v0"); |
637 fail("The test case is a prototype."); |
750 testUnreflectSpecial(Example.class, Example.class, Object.class, "v2", int.class, int.class); |
|
751 testUnreflectSpecial(Example.class, SubExample.class, Object.class, "v2", int.class, int.class); |
|
752 testUnreflectMaybeSpecial(Example.class, false, PRIVATE, Example.class, Example.class, void.class, "s0"); |
638 } |
753 } |
639 |
754 |
640 public static class HasFields { |
755 public static class HasFields { |
641 boolean fZ = false; |
756 boolean fZ = false; |
642 byte fB = (byte)'B'; |
757 byte fB = (byte)'B'; |
784 assertEquals(f.get(fields), value); // clean to start with |
899 assertEquals(f.get(fields), value); // clean to start with |
785 for (int i = 0; i <= 1; i++) { |
900 for (int i = 0; i <= 1; i++) { |
786 Object putValue = randomArg(type); |
901 Object putValue = randomArg(type); |
787 if (isStatic) { |
902 if (isStatic) { |
788 if (type == int.class) |
903 if (type == int.class) |
789 mh.<void>invoke((int)(Integer)putValue); // do these exactly |
904 mh.<void>invokeExact((int)(Integer)putValue); // do these exactly |
790 else |
905 else |
791 mh.<void>invoke(putValue); |
906 mh.<void>invokeExact(putValue); |
792 } else { |
907 } else { |
793 if (type == int.class) |
908 if (type == int.class) |
794 mh.<void>invoke((Object) fields, (int)(Integer)putValue); |
909 mh.<void>invokeExact((Object) fields, (int)(Integer)putValue); |
795 else |
910 else |
796 mh.<void>invoke((Object) fields, putValue); |
911 mh.<void>invokeExact((Object) fields, putValue); |
797 } |
912 } |
798 assertEquals(f.get(fields), putValue); |
913 assertEquals(f.get(fields), putValue); |
799 } |
914 } |
800 f.set(fields, value); // put it back |
915 f.set(fields, value); // put it back |
801 } |
916 } |
802 |
917 |
803 @Test |
918 @Test |
804 public void testArrayElementGetter() throws Throwable { |
919 public void testArrayElementGetter() throws Throwable { |
805 startTest("arrayElementGetter"); |
920 startTest("arrayElementGetter"); |
806 testArrayElementGetterSetter(new Object[10], false); |
921 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 } |
922 } |
812 |
923 |
813 @Test |
924 @Test |
814 public void testArrayElementSetter() throws Throwable { |
925 public void testArrayElementSetter() throws Throwable { |
815 startTest("arrayElementSetter"); |
926 startTest("arrayElementSetter"); |
816 testArrayElementGetterSetter(new Object[10], true); |
927 testArrayElementGetterSetter(true); |
817 testArrayElementGetterSetter(new String[10], true); |
928 } |
818 testArrayElementGetterSetter(new int[10], true); |
929 |
819 // FIXME: Do the other primitive types. |
930 public void testArrayElementGetterSetter(boolean testSetter) throws Throwable { |
820 //testArrayElementGetterSetter(new float[10], true); |
931 testArrayElementGetterSetter(new Object[10], testSetter); |
|
932 testArrayElementGetterSetter(new String[10], testSetter); |
|
933 testArrayElementGetterSetter(new boolean[10], testSetter); |
|
934 testArrayElementGetterSetter(new byte[10], testSetter); |
|
935 testArrayElementGetterSetter(new char[10], testSetter); |
|
936 testArrayElementGetterSetter(new short[10], testSetter); |
|
937 testArrayElementGetterSetter(new int[10], testSetter); |
|
938 testArrayElementGetterSetter(new float[10], testSetter); |
|
939 testArrayElementGetterSetter(new long[10], testSetter); |
|
940 testArrayElementGetterSetter(new double[10], testSetter); |
821 } |
941 } |
822 |
942 |
823 public void testArrayElementGetterSetter(Object array, boolean testSetter) throws Throwable { |
943 public void testArrayElementGetterSetter(Object array, boolean testSetter) throws Throwable { |
824 countTest(true); |
944 countTest(true); |
|
945 if (verbosity >= 2) System.out.println("array type = "+array.getClass().getComponentType().getName()+"["+Array.getLength(array)+"]"); |
825 Class<?> arrayType = array.getClass(); |
946 Class<?> arrayType = array.getClass(); |
826 Class<?> elemType = arrayType.getComponentType(); |
947 Class<?> elemType = arrayType.getComponentType(); |
827 MethodType expType = !testSetter |
948 MethodType expType = !testSetter |
828 ? MethodType.methodType(elemType, arrayType, int.class) |
949 ? MethodType.methodType(elemType, arrayType, int.class) |
829 : MethodType.methodType(void.class, arrayType, int.class, elemType); |
950 : MethodType.methodType(void.class, arrayType, int.class, elemType); |
830 MethodHandle mh = !testSetter |
951 MethodHandle mh = !testSetter |
831 ? MethodHandles.arrayElementGetter(arrayType) |
952 ? MethodHandles.arrayElementGetter(arrayType) |
832 : MethodHandles.arrayElementSetter(arrayType); |
953 : MethodHandles.arrayElementSetter(arrayType); |
833 assertSame(mh.type(), expType); |
954 assertSame(mh.type(), expType); |
834 //assertEquals(mh.toString(), f.getName()); |
955 if (elemType != int.class && elemType != boolean.class) { |
|
956 MethodType gtype; |
|
957 if (true) { // FIXME: remove this path (and remove <void> below in the mh.invokes) |
|
958 gtype = mh.type().changeParameterType(0, Object.class); |
|
959 if (testSetter) |
|
960 gtype = gtype.changeParameterType(2, Object.class); |
|
961 else |
|
962 gtype = gtype.changeReturnType(Object.class); |
|
963 } else |
|
964 // FIXME: This simpler path hits a bug in convertArguments => ToGeneric |
|
965 gtype = mh.type().generic().changeParameterType(1, int.class); |
|
966 mh = MethodHandles.convertArguments(mh, gtype); |
|
967 } |
835 Object sawValue, expValue; |
968 Object sawValue, expValue; |
836 List<Object> model = array2list(array); |
969 List<Object> model = array2list(array); |
837 int length = Array.getLength(array); |
970 int length = Array.getLength(array); |
838 for (int i = 0; i < length; i++) { |
971 for (int i = 0; i < length; i++) { |
839 // update array element |
972 // update array element |
840 Object random = randomArg(elemType); |
973 Object random = randomArg(elemType); |
841 model.set(i, random); |
974 model.set(i, random); |
842 if (testSetter) { |
975 if (testSetter) { |
843 if (elemType == int.class) |
976 if (elemType == int.class) |
844 mh.<void>invoke((int[]) array, i, (int)(Integer)random); |
977 mh.<void>invokeExact((int[]) array, i, (int)(Integer)random); |
|
978 else if (elemType == boolean.class) |
|
979 mh.<void>invokeExact((boolean[]) array, i, (boolean)(Boolean)random); |
845 else |
980 else |
846 mh.invokeGeneric(array, i, random); |
981 mh.<void>invokeExact(array, i, random); |
847 assertEquals(model, array2list(array)); |
982 assertEquals(model, array2list(array)); |
848 } else { |
983 } else { |
849 Array.set(array, i, random); |
984 Array.set(array, i, random); |
850 |
985 } |
|
986 if (verbosity >= 5) { |
|
987 List<Object> array2list = array2list(array); |
|
988 System.out.println("a["+i+"]="+random+" => "+array2list); |
|
989 if (!array2list.equals(model)) |
|
990 System.out.println("*** != "+model); |
851 } |
991 } |
852 // observe array element |
992 // observe array element |
853 sawValue = Array.get(array, i); |
993 sawValue = Array.get(array, i); |
854 if (!testSetter) { |
994 if (!testSetter) { |
855 expValue = sawValue; |
995 expValue = sawValue; |
856 if (elemType == int.class) |
996 if (elemType == int.class) |
857 sawValue = mh.<int>invoke((int[]) array, i); |
997 sawValue = mh.<int>invokeExact((int[]) array, i); |
|
998 else if (elemType == boolean.class) |
|
999 sawValue = mh.<boolean>invokeExact((boolean[]) array, i); |
858 else |
1000 else |
859 sawValue = mh.invokeGeneric(array, i); |
1001 sawValue = mh.invokeExact(array, i); |
860 assertEquals(sawValue, expValue); |
1002 assertEquals(sawValue, expValue); |
861 assertEquals(model, array2list(array)); |
1003 assertEquals(model, array2list(array)); |
862 } |
1004 } |
863 } |
1005 } |
864 } |
1006 } |
1081 @Test |
1226 @Test |
1082 public void testSpreadArguments() throws Throwable { |
1227 public void testSpreadArguments() throws Throwable { |
1083 if (CAN_SKIP_WORKING) return; |
1228 if (CAN_SKIP_WORKING) return; |
1084 startTest("spreadArguments"); |
1229 startTest("spreadArguments"); |
1085 for (Class<?> argType : new Class[]{Object.class, Integer.class, int.class}) { |
1230 for (Class<?> argType : new Class[]{Object.class, Integer.class, int.class}) { |
1086 if (verbosity >= 2) |
1231 if (verbosity >= 3) |
1087 System.out.println("spreadArguments "+argType); |
1232 System.out.println("spreadArguments "+argType); |
|
1233 // FIXME: enable _adapter_spread_args and fix Fail_2 |
1088 for (int nargs = 0; nargs < 10; nargs++) { |
1234 for (int nargs = 0; nargs < 10; nargs++) { |
1089 if (argType == int.class && nargs >= 6) continue; // FIXME Fail_1 |
1235 if (argType == int.class && nargs >= 6) continue; // FIXME Fail_1 |
1090 for (int pos = 0; pos < nargs; pos++) { |
1236 for (int pos = 0; pos < nargs; pos++) { |
1091 if (argType == int.class && pos > 0) continue; // FIXME Fail_3 |
1237 if (argType == int.class && pos > 0) continue; // FIXME Fail_3 |
1092 testSpreadArguments(argType, pos, nargs); |
1238 testSpreadArguments(argType, pos, nargs); |
1093 } |
1239 } |
1094 } |
1240 } |
1095 } |
1241 } |
1096 } |
1242 } |
1097 public void testSpreadArguments(Class<?> argType, int pos, int nargs) throws Throwable { |
1243 public void testSpreadArguments(Class<?> argType, int pos, int nargs) throws Throwable { |
1098 countTest(); |
1244 countTest(); |
1099 MethodHandle target = ValueConversions.varargsArray(nargs); |
1245 MethodHandle target = ValueConversions.varargsArray(nargs); |
1100 MethodHandle target2 = changeArgTypes(target, argType); |
1246 MethodHandle target2 = changeArgTypes(target, argType); |
1101 if (verbosity >= 2) |
1247 if (verbosity >= 3) |
1102 System.out.println("spread into "+target2+" ["+pos+".."+nargs+"]"); |
1248 System.out.println("spread into "+target2+" ["+pos+".."+nargs+"]"); |
1103 Object[] args = randomArgs(target2.type().parameterArray()); |
1249 Object[] args = randomArgs(target2.type().parameterArray()); |
1104 // make sure the target does what we think it does: |
1250 // make sure the target does what we think it does: |
1105 if (pos == 0 && nargs < 5) { |
1251 if (pos == 0 && nargs < 5) { |
1106 Object[] check = (Object[]) target.invokeVarargs(args); |
1252 Object[] check = (Object[]) target.invokeVarargs(args); |
1107 assertArrayEquals(args, check); |
1253 assertArrayEquals(args, check); |
1108 switch (nargs) { |
1254 switch (nargs) { |
1109 case 0: |
1255 case 0: |
1110 check = target.<Object[]>invoke(); |
1256 check = target.<Object[]>invokeExact(); |
1111 assertArrayEquals(args, check); |
1257 assertArrayEquals(args, check); |
1112 break; |
1258 break; |
1113 case 1: |
1259 case 1: |
1114 check = target.<Object[]>invoke(args[0]); |
1260 check = target.<Object[]>invokeExact(args[0]); |
1115 assertArrayEquals(args, check); |
1261 assertArrayEquals(args, check); |
1116 break; |
1262 break; |
1117 case 2: |
1263 case 2: |
1118 check = target.<Object[]>invoke(args[0], args[1]); |
1264 check = target.<Object[]>invokeExact(args[0], args[1]); |
1119 assertArrayEquals(args, check); |
1265 assertArrayEquals(args, check); |
1120 break; |
1266 break; |
1121 } |
1267 } |
1122 } |
1268 } |
1123 List<Class<?>> newParams = new ArrayList<Class<?>>(target2.type().parameterList()); |
1269 List<Class<?>> newParams = new ArrayList<Class<?>>(target2.type().parameterList()); |
1393 if (testRetCode) assertEquals(code, result); |
1539 if (testRetCode) assertEquals(code, result); |
1394 assertCalled("invokee", args); |
1540 assertCalled("invokee", args); |
1395 // varargs invoker #0 |
1541 // varargs invoker #0 |
1396 calledLog.clear(); |
1542 calledLog.clear(); |
1397 inv = MethodHandles.varargsInvoker(type, 0); |
1543 inv = MethodHandles.varargsInvoker(type, 0); |
1398 result = inv.invoke(target, args); |
1544 result = inv.invokeExact(target, args); |
1399 if (testRetCode) assertEquals(code, result); |
1545 if (testRetCode) assertEquals(code, result); |
1400 assertCalled("invokee", args); |
1546 assertCalled("invokee", args); |
1401 if (nargs >= 1) { |
1547 if (nargs >= 1) { |
1402 // varargs invoker #1 |
1548 // varargs invoker #1 |
1403 calledLog.clear(); |
1549 calledLog.clear(); |
1404 inv = MethodHandles.varargsInvoker(type, 1); |
1550 inv = MethodHandles.varargsInvoker(type, 1); |
1405 result = inv.invoke(target, args[0], Arrays.copyOfRange(args, 1, nargs)); |
1551 result = inv.invokeExact(target, args[0], Arrays.copyOfRange(args, 1, nargs)); |
1406 if (testRetCode) assertEquals(code, result); |
1552 if (testRetCode) assertEquals(code, result); |
1407 assertCalled("invokee", args); |
1553 assertCalled("invokee", args); |
1408 } |
1554 } |
1409 if (nargs >= 2) { |
1555 if (nargs >= 2) { |
1410 // varargs invoker #2 |
1556 // varargs invoker #2 |
1411 calledLog.clear(); |
1557 calledLog.clear(); |
1412 inv = MethodHandles.varargsInvoker(type, 2); |
1558 inv = MethodHandles.varargsInvoker(type, 2); |
1413 result = inv.invoke(target, args[0], args[1], Arrays.copyOfRange(args, 2, nargs)); |
1559 result = inv.invokeExact(target, args[0], args[1], Arrays.copyOfRange(args, 2, nargs)); |
1414 if (testRetCode) assertEquals(code, result); |
1560 if (testRetCode) assertEquals(code, result); |
1415 assertCalled("invokee", args); |
1561 assertCalled("invokee", args); |
1416 } |
1562 } |
1417 if (nargs >= 3) { |
1563 if (nargs >= 3) { |
1418 // varargs invoker #3 |
1564 // varargs invoker #3 |
1419 calledLog.clear(); |
1565 calledLog.clear(); |
1420 inv = MethodHandles.varargsInvoker(type, 3); |
1566 inv = MethodHandles.varargsInvoker(type, 3); |
1421 result = inv.invoke(target, args[0], args[1], args[2], Arrays.copyOfRange(args, 3, nargs)); |
1567 result = inv.invokeExact(target, args[0], args[1], args[2], Arrays.copyOfRange(args, 3, nargs)); |
1422 if (testRetCode) assertEquals(code, result); |
1568 if (testRetCode) assertEquals(code, result); |
1423 assertCalled("invokee", args); |
1569 assertCalled("invokee", args); |
1424 } |
1570 } |
1425 for (int k = 0; k <= nargs; k++) { |
1571 for (int k = 0; k <= nargs; k++) { |
1426 // varargs invoker #0..N |
1572 // varargs invoker #0..N |