blob: 3026be1deb3f30e26c232148ada8002a4ff11f5e [file] [log] [blame]
Narayan Kamath000e1882016-10-24 17:14:25 +01001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17import java.lang.invoke.MethodHandle;
18import java.lang.invoke.MethodHandles;
19import java.lang.invoke.MethodHandles.Lookup;
20import java.lang.invoke.MethodType;
21import java.lang.invoke.WrongMethodTypeException;
Narayan Kamath000e1882016-10-24 17:14:25 +010022
23public class Main {
Narayan Kamath000e1882016-10-24 17:14:25 +010024 public static void main(String[] args) throws Throwable {
25 testThrowException();
Narayan Kamath96120f42016-11-01 09:40:23 +000026 testDropArguments();
27 testCatchException();
28 testGuardWithTest();
Narayan Kamath3314dbb2016-11-03 18:01:32 +000029 testArrayElementGetter();
30 testArrayElementSetter();
31 testIdentity();
32 testConstant();
Narayan Kamath8677d0b2016-11-04 14:41:19 +000033 testBindTo();
Narayan Kamath916a7712016-11-08 18:36:16 +000034 testFilterReturnValue();
Narayan Kamath000e1882016-10-24 17:14:25 +010035 }
36
37 public static void testThrowException() throws Throwable {
38 MethodHandle handle = MethodHandles.throwException(String.class,
39 IllegalArgumentException.class);
40
41 if (handle.type().returnType() != String.class) {
42 System.out.println("Unexpected return type for handle: " + handle +
43 " [ " + handle.type() + "]");
44 }
45
Narayan Kamath96120f42016-11-01 09:40:23 +000046 final IllegalArgumentException iae = new IllegalArgumentException("boo!");
Narayan Kamath000e1882016-10-24 17:14:25 +010047 try {
Narayan Kamath96120f42016-11-01 09:40:23 +000048 handle.invoke(iae);
Narayan Kamath000e1882016-10-24 17:14:25 +010049 System.out.println("Expected an exception of type: java.lang.IllegalArgumentException");
50 } catch (IllegalArgumentException expected) {
Narayan Kamath96120f42016-11-01 09:40:23 +000051 if (expected != iae) {
52 System.out.println("Wrong exception: expected " + iae + " but was " + expected);
53 }
Narayan Kamath000e1882016-10-24 17:14:25 +010054 }
55 }
Narayan Kamath96120f42016-11-01 09:40:23 +000056
57 public static void dropArguments_delegate(String message, long message2) {
58 System.out.println("Message: " + message + ", Message2: " + message2);
59 }
60
61 public static void testDropArguments() throws Throwable {
62 MethodHandle delegate = MethodHandles.lookup().findStatic(Main.class,
63 "dropArguments_delegate",
64 MethodType.methodType(void.class, new Class<?>[] { String.class, long.class }));
65
66 MethodHandle transform = MethodHandles.dropArguments(delegate, 0, int.class, Object.class);
67
68 // The transformer will accept two additional arguments at position zero.
69 try {
70 transform.invokeExact("foo", 42l);
71 fail();
72 } catch (WrongMethodTypeException expected) {
73 }
74
75 transform.invokeExact(45, new Object(), "foo", 42l);
76 transform.invoke(45, new Object(), "foo", 42l);
77
78 // Additional arguments at position 1.
79 transform = MethodHandles.dropArguments(delegate, 1, int.class, Object.class);
80 transform.invokeExact("foo", 45, new Object(), 42l);
81 transform.invoke("foo", 45, new Object(), 42l);
82
83 // Additional arguments at position 2.
84 transform = MethodHandles.dropArguments(delegate, 2, int.class, Object.class);
85 transform.invokeExact("foo", 42l, 45, new Object());
86 transform.invoke("foo", 42l, 45, new Object());
87
88 // Note that we still perform argument conversions even for the arguments that
89 // are subsequently dropped.
90 try {
91 transform.invoke("foo", 42l, 45l, new Object());
92 fail();
93 } catch (WrongMethodTypeException expected) {
94 } catch (IllegalArgumentException expected) {
95 // TODO(narayan): We currently throw the wrong type of exception here,
96 // it's IAE and should be WMTE instead.
97 }
98
Narayan Kamath0a8485e2016-11-02 18:47:11 +000099 // Check that asType works as expected.
100 transform = MethodHandles.dropArguments(delegate, 0, int.class, Object.class);
101 transform = transform.asType(MethodType.methodType(void.class,
102 new Class<?>[] { short.class, Object.class, String.class, long.class }));
103 transform.invokeExact((short) 45, new Object(), "foo", 42l);
104
Narayan Kamath96120f42016-11-01 09:40:23 +0000105 // Invalid argument location, should not be allowed.
106 try {
107 MethodHandles.dropArguments(delegate, -1, int.class, Object.class);
108 fail();
109 } catch (IllegalArgumentException expected) {
110 }
111
112 // Invalid argument location, should not be allowed.
113 try {
114 MethodHandles.dropArguments(delegate, 3, int.class, Object.class);
115 fail();
116 } catch (IllegalArgumentException expected) {
117 }
118
119 try {
120 MethodHandles.dropArguments(delegate, 1, void.class);
121 fail();
122 } catch (IllegalArgumentException expected) {
123 }
124 }
125
126 public static String testCatchException_target(String arg1, long arg2, String exceptionMessage)
127 throws Throwable {
128 if (exceptionMessage != null) {
129 throw new IllegalArgumentException(exceptionMessage);
130 }
131
132 System.out.println("Target: Arg1: " + arg1 + ", Arg2: " + arg2);
133 return "target";
134 }
135
136 public static String testCatchException_handler(IllegalArgumentException iae, String arg1, long arg2,
137 String exMsg) {
138 System.out.println("Handler: " + iae + ", Arg1: " + arg1 + ", Arg2: " + arg2 + ", ExMsg: " + exMsg);
139 return "handler1";
140 }
141
142 public static String testCatchException_handler2(IllegalArgumentException iae, String arg1) {
143 System.out.println("Handler: " + iae + ", Arg1: " + arg1);
144 return "handler2";
145 }
146
147 public static void testCatchException() throws Throwable {
148 MethodHandle target = MethodHandles.lookup().findStatic(Main.class,
149 "testCatchException_target",
150 MethodType.methodType(String.class, new Class<?>[] { String.class, long.class, String.class }));
151
152 MethodHandle handler = MethodHandles.lookup().findStatic(Main.class,
153 "testCatchException_handler",
154 MethodType.methodType(String.class, new Class<?>[] { IllegalArgumentException.class,
155 String.class, long.class, String.class }));
156
157 MethodHandle adapter = MethodHandles.catchException(target, IllegalArgumentException.class,
158 handler);
159
160 String returnVal = null;
161
162 // These two should end up calling the target always. We're passing a null exception
163 // message here, which means the target will not throw.
164 returnVal = (String) adapter.invoke("foo", 42, null);
165 assertEquals("target", returnVal);
166 returnVal = (String) adapter.invokeExact("foo", 42l, (String) null);
167 assertEquals("target", returnVal);
168
169 // We're passing a non-null exception message here, which means the target will throw,
170 // which in turn means that the handler must be called for the next two invokes.
171 returnVal = (String) adapter.invoke("foo", 42, "exceptionMessage");
172 assertEquals("handler1", returnVal);
173 returnVal = (String) adapter.invokeExact("foo", 42l, "exceptionMessage");
174 assertEquals("handler1", returnVal);
175
176 handler = MethodHandles.lookup().findStatic(Main.class,
177 "testCatchException_handler2",
178 MethodType.methodType(String.class, new Class<?>[] { IllegalArgumentException.class,
179 String.class }));
180 adapter = MethodHandles.catchException(target, IllegalArgumentException.class, handler);
181
182 returnVal = (String) adapter.invoke("foo", 42, "exceptionMessage");
183 assertEquals("handler2", returnVal);
184 returnVal = (String) adapter.invokeExact("foo", 42l, "exceptionMessage");
185 assertEquals("handler2", returnVal);
186
187 // Test that the type of the invoke doesn't matter. Here we call
188 // IllegalArgumentException.toString() on the exception that was thrown by
189 // the target.
190 handler = MethodHandles.lookup().findVirtual(IllegalArgumentException.class,
191 "toString", MethodType.methodType(String.class));
192 adapter = MethodHandles.catchException(target, IllegalArgumentException.class, handler);
193
194 returnVal = (String) adapter.invoke("foo", 42, "exceptionMessage");
195 assertEquals("java.lang.IllegalArgumentException: exceptionMessage", returnVal);
196 returnVal = (String) adapter.invokeExact("foo", 42l, "exceptionMessage2");
197 assertEquals("java.lang.IllegalArgumentException: exceptionMessage2", returnVal);
Narayan Kamath0a8485e2016-11-02 18:47:11 +0000198
199 // Check that asType works as expected.
200 adapter = MethodHandles.catchException(target, IllegalArgumentException.class,
201 handler);
202 adapter = adapter.asType(MethodType.methodType(String.class,
203 new Class<?>[] { String.class, int.class, String.class }));
204 returnVal = (String) adapter.invokeExact("foo", 42, "exceptionMessage");
205 assertEquals("java.lang.IllegalArgumentException: exceptionMessage", returnVal);
Narayan Kamath96120f42016-11-01 09:40:23 +0000206 }
207
208 public static boolean testGuardWithTest_test(String arg1, long arg2) {
209 return "target".equals(arg1) && 42 == arg2;
210 }
211
212 public static String testGuardWithTest_target(String arg1, long arg2, int arg3) {
213 System.out.println("target: " + arg1 + ", " + arg2 + ", " + arg3);
214 return "target";
215 }
216
217 public static String testGuardWithTest_fallback(String arg1, long arg2, int arg3) {
218 System.out.println("fallback: " + arg1 + ", " + arg2 + ", " + arg3);
219 return "fallback";
220 }
221
222 public static void testGuardWithTest() throws Throwable {
223 MethodHandle test = MethodHandles.lookup().findStatic(Main.class,
224 "testGuardWithTest_test",
225 MethodType.methodType(boolean.class, new Class<?>[] { String.class, long.class }));
226
227 final MethodType type = MethodType.methodType(String.class,
228 new Class<?>[] { String.class, long.class, int.class });
229
230 final MethodHandle target = MethodHandles.lookup().findStatic(Main.class,
231 "testGuardWithTest_target", type);
232 final MethodHandle fallback = MethodHandles.lookup().findStatic(Main.class,
233 "testGuardWithTest_fallback", type);
234
235 MethodHandle adapter = MethodHandles.guardWithTest(test, target, fallback);
236
237 String returnVal = null;
238
239 returnVal = (String) adapter.invoke("target", 42, 56);
240 assertEquals("target", returnVal);
241 returnVal = (String) adapter.invokeExact("target", 42l, 56);
242 assertEquals("target", returnVal);
243
244 returnVal = (String) adapter.invoke("fallback", 42l, 56);
245 assertEquals("fallback", returnVal);
246 returnVal = (String) adapter.invokeExact("target", 42l, 56);
247 assertEquals("target", returnVal);
Narayan Kamath0a8485e2016-11-02 18:47:11 +0000248
249 // Check that asType works as expected.
250 adapter = adapter.asType(MethodType.methodType(String.class,
251 new Class<?>[] { String.class, int.class, int.class }));
252 returnVal = (String) adapter.invokeExact("target", 42, 56);
253 assertEquals("target", returnVal);
Narayan Kamath96120f42016-11-01 09:40:23 +0000254 }
255
Narayan Kamath3314dbb2016-11-03 18:01:32 +0000256 public static void testArrayElementGetter() throws Throwable {
257 MethodHandle getter = MethodHandles.arrayElementGetter(int[].class);
258
259 {
260 int[] array = new int[1];
261 array[0] = 42;
262 int value = (int) getter.invoke(array, 0);
263 if (value != 42) {
264 System.out.println("Unexpected value: " + value);
265 }
266
267 try {
268 value = (int) getter.invoke(array, -1);
269 fail();
270 } catch (ArrayIndexOutOfBoundsException expected) {
271 }
272
273 try {
274 value = (int) getter.invoke(null, -1);
275 fail();
276 } catch (NullPointerException expected) {
277 }
278 }
279
280 {
281 getter = MethodHandles.arrayElementGetter(long[].class);
282 long[] array = new long[1];
283 array[0] = 42;
284 long value = (long) getter.invoke(array, 0);
285 if (value != 42l) {
286 System.out.println("Unexpected value: " + value);
287 }
288 }
289
290 {
291 getter = MethodHandles.arrayElementGetter(short[].class);
292 short[] array = new short[1];
293 array[0] = 42;
294 short value = (short) getter.invoke(array, 0);
295 if (value != 42l) {
296 System.out.println("Unexpected value: " + value);
297 }
298 }
299
300 {
301 getter = MethodHandles.arrayElementGetter(char[].class);
302 char[] array = new char[1];
303 array[0] = 42;
304 char value = (char) getter.invoke(array, 0);
305 if (value != 42l) {
306 System.out.println("Unexpected value: " + value);
307 }
308 }
309
310 {
311 getter = MethodHandles.arrayElementGetter(byte[].class);
312 byte[] array = new byte[1];
313 array[0] = (byte) 0x8;
314 byte value = (byte) getter.invoke(array, 0);
315 if (value != (byte) 0x8) {
316 System.out.println("Unexpected value: " + value);
317 }
318 }
319
320 {
321 getter = MethodHandles.arrayElementGetter(boolean[].class);
322 boolean[] array = new boolean[1];
323 array[0] = true;
324 boolean value = (boolean) getter.invoke(array, 0);
325 if (!value) {
326 System.out.println("Unexpected value: " + value);
327 }
328 }
329
330 {
331 getter = MethodHandles.arrayElementGetter(float[].class);
332 float[] array = new float[1];
333 array[0] = 42.0f;
334 float value = (float) getter.invoke(array, 0);
335 if (value != 42.0f) {
336 System.out.println("Unexpected value: " + value);
337 }
338 }
339
340 {
341 getter = MethodHandles.arrayElementGetter(double[].class);
342 double[] array = new double[1];
343 array[0] = 42.0;
344 double value = (double) getter.invoke(array, 0);
345 if (value != 42.0) {
346 System.out.println("Unexpected value: " + value);
347 }
348 }
349
350 {
351 getter = MethodHandles.arrayElementGetter(String[].class);
352 String[] array = new String[3];
353 array[0] = "42";
354 array[1] = "48";
355 array[2] = "54";
356 String value = (String) getter.invoke(array, 0);
357 assertEquals("42", value);
358 value = (String) getter.invoke(array, 1);
359 assertEquals("48", value);
360 value = (String) getter.invoke(array, 2);
361 assertEquals("54", value);
362 }
363 }
364
365 public static void testArrayElementSetter() throws Throwable {
366 MethodHandle setter = MethodHandles.arrayElementSetter(int[].class);
367
368 {
369 int[] array = new int[2];
370 setter.invoke(array, 0, 42);
371 setter.invoke(array, 1, 43);
372
373 if (array[0] != 42) {
374 System.out.println("Unexpected value: " + array[0]);
375 }
376 if (array[1] != 43) {
377 System.out.println("Unexpected value: " + array[1]);
378 }
379
380 try {
381 setter.invoke(array, -1, 42);
382 fail();
383 } catch (ArrayIndexOutOfBoundsException expected) {
384 }
385
386 try {
387 setter.invoke(null, 0, 42);
388 fail();
389 } catch (NullPointerException expected) {
390 }
391 }
392
393 {
394 setter = MethodHandles.arrayElementSetter(long[].class);
395 long[] array = new long[1];
396 setter.invoke(array, 0, 42l);
397 if (array[0] != 42l) {
398 System.out.println("Unexpected value: " + array[0]);
399 }
400 }
401
402 {
403 setter = MethodHandles.arrayElementSetter(short[].class);
404 short[] array = new short[1];
405 setter.invoke(array, 0, (short) 42);
406 if (array[0] != 42l) {
407 System.out.println("Unexpected value: " + array[0]);
408 }
409 }
410
411 {
412 setter = MethodHandles.arrayElementSetter(char[].class);
413 char[] array = new char[1];
414 setter.invoke(array, 0, (char) 42);
415 if (array[0] != 42) {
416 System.out.println("Unexpected value: " + array[0]);
417 }
418 }
419
420 {
421 setter = MethodHandles.arrayElementSetter(byte[].class);
422 byte[] array = new byte[1];
423 setter.invoke(array, 0, (byte) 0x8);
424 if (array[0] != (byte) 0x8) {
425 System.out.println("Unexpected value: " + array[0]);
426 }
427 }
428
429 {
430 setter = MethodHandles.arrayElementSetter(boolean[].class);
431 boolean[] array = new boolean[1];
432 setter.invoke(array, 0, true);
433 if (!array[0]) {
434 System.out.println("Unexpected value: " + array[0]);
435 }
436 }
437
438 {
439 setter = MethodHandles.arrayElementSetter(float[].class);
440 float[] array = new float[1];
441 setter.invoke(array, 0, 42.0f);
442 if (array[0] != 42.0f) {
443 System.out.println("Unexpected value: " + array[0]);
444 }
445 }
446
447 {
448 setter = MethodHandles.arrayElementSetter(double[].class);
449 double[] array = new double[1];
450 setter.invoke(array, 0, 42.0);
451 if (array[0] != 42.0) {
452 System.out.println("Unexpected value: " + array[0]);
453 }
454 }
455
456 {
457 setter = MethodHandles.arrayElementSetter(String[].class);
458 String[] array = new String[3];
459 setter.invoke(array, 0, "42");
460 setter.invoke(array, 1, "48");
461 setter.invoke(array, 2, "54");
462 assertEquals("42", array[0]);
463 assertEquals("48", array[1]);
464 assertEquals("54", array[2]);
465 }
466 }
467
468 public static void testIdentity() throws Throwable {
469 {
470 MethodHandle identity = MethodHandles.identity(boolean.class);
471 boolean value = (boolean) identity.invoke(false);
472 if (value) {
473 System.out.println("Unexpected value: " + value);
474 }
475 }
476
477 {
478 MethodHandle identity = MethodHandles.identity(byte.class);
479 byte value = (byte) identity.invoke((byte) 0x8);
480 if (value != (byte) 0x8) {
481 System.out.println("Unexpected value: " + value);
482 }
483 }
484
485 {
486 MethodHandle identity = MethodHandles.identity(char.class);
487 char value = (char) identity.invoke((char) -56);
488 if (value != (char) -56) {
489 System.out.println("Unexpected value: " + value);
490 }
491 }
492
493 {
494 MethodHandle identity = MethodHandles.identity(short.class);
495 short value = (short) identity.invoke((short) -59);
496 if (value != (short) -59) {
497 System.out.println("Unexpected value: " + value);
498 }
499 }
500
501 {
502 MethodHandle identity = MethodHandles.identity(int.class);
503 int value = (int) identity.invoke(52);
504 if (value != 52) {
505 System.out.println("Unexpected value: " + value);
506 }
507 }
508
509 {
510 MethodHandle identity = MethodHandles.identity(long.class);
511 long value = (long) identity.invoke(-76l);
512 if (value != (long) -76) {
513 System.out.println("Unexpected value: " + value);
514 }
515 }
516
517 {
518 MethodHandle identity = MethodHandles.identity(float.class);
519 float value = (float) identity.invoke(56.0f);
520 if (value != (float) 56.0f) {
521 System.out.println("Unexpected value: " + value);
522 }
523 }
524
525 {
526 MethodHandle identity = MethodHandles.identity(double.class);
527 double value = (double) identity.invoke((double) 72.0);
528 if (value != (double) 72.0) {
529 System.out.println("Unexpected value: " + value);
530 }
531 }
532
533 {
534 MethodHandle identity = MethodHandles.identity(String.class);
535 String value = (String) identity.invoke("bazman");
536 assertEquals("bazman", value);
537 }
538 }
539
540 public static void testConstant() throws Throwable {
541 // int constants.
542 {
543 MethodHandle constant = MethodHandles.constant(int.class, 56);
544 int value = (int) constant.invoke();
545 if (value != 56) {
546 System.out.println("Unexpected value: " + value);
547 }
548
549 // short constant values are converted to int.
550 constant = MethodHandles.constant(int.class, (short) 52);
551 value = (int) constant.invoke();
552 if (value != 52) {
553 System.out.println("Unexpected value: " + value);
554 }
555
556 // char constant values are converted to int.
557 constant = MethodHandles.constant(int.class, (char) 'b');
558 value = (int) constant.invoke();
559 if (value != (int) 'b') {
560 System.out.println("Unexpected value: " + value);
561 }
562
563 // int constant values are converted to int.
564 constant = MethodHandles.constant(int.class, (byte) 0x1);
565 value = (int) constant.invoke();
566 if (value != 1) {
567 System.out.println("Unexpected value: " + value);
568 }
569
570 // boolean, float, double and long primitive constants are not convertible
571 // to int, so the handle creation must fail with a CCE.
572 try {
573 MethodHandles.constant(int.class, false);
574 fail();
575 } catch (ClassCastException expected) {
576 }
577
578 try {
579 MethodHandles.constant(int.class, 0.1f);
580 fail();
581 } catch (ClassCastException expected) {
582 }
583
584 try {
585 MethodHandles.constant(int.class, 0.2);
586 fail();
587 } catch (ClassCastException expected) {
588 }
589
590 try {
591 MethodHandles.constant(int.class, 73l);
592 fail();
593 } catch (ClassCastException expected) {
594 }
595 }
596
597 // long constants.
598 {
599 MethodHandle constant = MethodHandles.constant(long.class, 56l);
600 long value = (long) constant.invoke();
601 if (value != 56l) {
602 System.out.println("Unexpected value: " + value);
603 }
604
605 constant = MethodHandles.constant(long.class, (int) 56);
606 value = (long) constant.invoke();
607 if (value != 56l) {
608 System.out.println("Unexpected value: " + value);
609 }
610 }
611
612 // byte constants.
613 {
614 MethodHandle constant = MethodHandles.constant(byte.class, (byte) 0x12);
615 byte value = (byte) constant.invoke();
616 if (value != (byte) 0x12) {
617 System.out.println("Unexpected value: " + value);
618 }
619 }
620
621 // boolean constants.
622 {
623 MethodHandle constant = MethodHandles.constant(boolean.class, true);
624 boolean value = (boolean) constant.invoke();
625 if (!value) {
626 System.out.println("Unexpected value: " + value);
627 }
628 }
629
630 // char constants.
631 {
632 MethodHandle constant = MethodHandles.constant(char.class, 'f');
633 char value = (char) constant.invoke();
634 if (value != 'f') {
635 System.out.println("Unexpected value: " + value);
636 }
637 }
638
639 // short constants.
640 {
641 MethodHandle constant = MethodHandles.constant(short.class, (short) 123);
642 short value = (short) constant.invoke();
643 if (value != (short) 123) {
644 System.out.println("Unexpected value: " + value);
645 }
646 }
647
648 // float constants.
649 {
650 MethodHandle constant = MethodHandles.constant(float.class, 56.0f);
651 float value = (float) constant.invoke();
652 if (value != 56.0f) {
653 System.out.println("Unexpected value: " + value);
654 }
655 }
656
657 // double constants.
658 {
659 MethodHandle constant = MethodHandles.constant(double.class, 256.0);
660 double value = (double) constant.invoke();
661 if (value != 256.0) {
662 System.out.println("Unexpected value: " + value);
663 }
664 }
665
666 // reference constants.
667 {
668 MethodHandle constant = MethodHandles.constant(String.class, "256.0");
669 String value = (String) constant.invoke();
670 assertEquals("256.0", value);
671 }
672 }
673
Narayan Kamath8677d0b2016-11-04 14:41:19 +0000674 public static void testBindTo() throws Throwable {
675 MethodHandle stringCharAt = MethodHandles.lookup().findVirtual(
676 String.class, "charAt", MethodType.methodType(char.class, int.class));
677
678 char value = (char) stringCharAt.invoke("foo", 0);
679 if (value != 'f') {
680 System.out.println("Unexpected value: " + value);
681 }
682
683 MethodHandle bound = stringCharAt.bindTo("foo");
684 value = (char) bound.invoke(0);
685 if (value != 'f') {
686 System.out.println("Unexpected value: " + value);
687 }
688
689 try {
690 stringCharAt.bindTo(new Object());
691 fail();
692 } catch (ClassCastException expected) {
693 }
694
695 bound = stringCharAt.bindTo(null);
696 try {
697 bound.invoke(0);
698 fail();
699 } catch (NullPointerException expected) {
700 }
701
702 MethodHandle integerParseInt = MethodHandles.lookup().findStatic(
703 Integer.class, "parseInt", MethodType.methodType(int.class, String.class));
704
705 bound = integerParseInt.bindTo("78452");
706 int intValue = (int) bound.invoke();
707 if (intValue != 78452) {
708 System.out.println("Unexpected value: " + intValue);
709 }
710 }
711
Narayan Kamath916a7712016-11-08 18:36:16 +0000712 public static String filterReturnValue_target(int a) {
713 return "ReturnValue" + a;
714 }
715
716 public static boolean filterReturnValue_filter(String value) {
717 return value.indexOf("42") != -1;
718 }
719
720 public static int filterReturnValue_intTarget(String a) {
721 return Integer.parseInt(a);
722 }
723
724 public static int filterReturnValue_intFilter(int b) {
725 return b + 1;
726 }
727
728 public static void filterReturnValue_voidTarget() {
729 }
730
731 public static int filterReturnValue_voidFilter() {
732 return 42;
733 }
734
735 public static void testFilterReturnValue() throws Throwable {
736 // A target that returns a reference.
737 {
738 final MethodHandle target = MethodHandles.lookup().findStatic(Main.class,
739 "filterReturnValue_target", MethodType.methodType(String.class, int.class));
740 final MethodHandle filter = MethodHandles.lookup().findStatic(Main.class,
741 "filterReturnValue_filter", MethodType.methodType(boolean.class, String.class));
742
743 MethodHandle adapter = MethodHandles.filterReturnValue(target, filter);
744
745 boolean value = (boolean) adapter.invoke((int) 42);
746 if (!value) {
747 System.out.println("Unexpected value: " + value);
748 }
749 value = (boolean) adapter.invoke((int) 43);
750 if (value) {
751 System.out.println("Unexpected value: " + value);
752 }
753 }
754
755 // A target that returns a primitive.
756 {
757 final MethodHandle target = MethodHandles.lookup().findStatic(Main.class,
758 "filterReturnValue_intTarget", MethodType.methodType(int.class, String.class));
759 final MethodHandle filter = MethodHandles.lookup().findStatic(Main.class,
760 "filterReturnValue_intFilter", MethodType.methodType(int.class, int.class));
761
762 MethodHandle adapter = MethodHandles.filterReturnValue(target, filter);
763
764 int value = (int) adapter.invoke("56");
765 if (value != 57) {
766 System.out.println("Unexpected value: " + value);
767 }
768 }
769
770 // A target that returns void.
771 {
772 final MethodHandle target = MethodHandles.lookup().findStatic(Main.class,
773 "filterReturnValue_voidTarget", MethodType.methodType(void.class));
774 final MethodHandle filter = MethodHandles.lookup().findStatic(Main.class,
775 "filterReturnValue_voidFilter", MethodType.methodType(int.class));
776
777 MethodHandle adapter = MethodHandles.filterReturnValue(target, filter);
778
779 int value = (int) adapter.invoke();
780 if (value != 42) {
781 System.out.println("Unexpected value: " + value);
782 }
783 }
784 }
785
Narayan Kamath96120f42016-11-01 09:40:23 +0000786 public static void fail() {
787 System.out.println("FAIL");
788 Thread.dumpStack();
789 }
790
791 public static void assertEquals(String s1, String s2) {
792 if (s1 == s2) {
793 return;
794 }
795
796 if (s1 != null && s2 != null && s1.equals(s2)) {
797 return;
798 }
799
800 throw new AssertionError("assertEquals s1: " + s1 + ", s2: " + s2);
801 }
Narayan Kamath000e1882016-10-24 17:14:25 +0100802}